Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of non-blocking await for 6.d.PREVIEW #1004

Merged
merged 11 commits into from Jan 27, 2017

Conversation

jnthn
Copy link
Member

@jnthn jnthn commented Jan 25, 2017

So far, when you await in code running on a thread in the thread pool, it would block a real OS thread. This meant that certain patterns had to be expressed in unnatural ways (using .then and a callback), or that the scheduler had to have its maximum number of threads raised really high. For example, sleepsort on a hundred or a thousand values would run into issues there if you wrote it with await.

My original intention for await, when used on a thread pool thread, was that it would instead hand control back to the scheduler so the thread could be used for other work. This would mean we could have thousands of tasks awaiting stuff, and just a handful of threads required for progress.

This PR implements exactly that. As a bonus, it also makes await in the case of an already available result not require concurrency control in the Promise case, which should be a speed-up. Furthermore, there's now an interface for things that wish to participate in the await system to implement, so while we just use it for Promise, Supply, and Channel today, module space will also be able to create their own things that we can await.

Unless you use v6.d.PREVIEW, nothing changes as of merging this PR. You have to opt in to get this new behavior of await. Once Perl 6.d is released, then Rakudo will switch to 6.d being the default and - unless code has explicitly declared itself as wanting 6.c - this will become the default behavior for all awaits on thread pool threads. (And await in the mainline, or in a bare Thread, will continue to have the same blocking behavior as today, just implemented through the new Awaitable interface.)

jnthn and others added 11 commits January 25, 2017 12:18
For now, just a marker role for things that we can `await`. Later, it
it will require a method for subscribing a resumption.
Patch by nine++ cherry-picked and updated to build/work on HEAD.
This does not yet support non-blocking `await`, but the factoring is
designed to enable it to be put in place. For now, only Promise has
been updated to support `await` under the new factoring, and only a
single result may be `await`ed.
Now, if we do an `await` in code being run in the thread pool, and the
awaited value(s) are not yet available, we take a continuation. This
frees up the thread to process more work from the thread pool. When
all of the awaited results are available, or the production of one of
them produces an exception, then the resumption of the continuation
will be scheduled in the thread pool.

This behavior will only happen if you say `use v6.d.PREVIEW`.
Avoids some wasteful work as well as fixing a race.
has Mu $.result;
has Exception $.cause;

method already-success(\result) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strangely I was thinking about this the other day, there seems to be a pattern in Scala where a method that returns a Future may return a Future.failed directly rather than throwing an exception.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been considering Promise.kept(value) and Promise.broken(exception) Promise factories that would cheaply create such Promise objects. Ran into a few situations in my own code where I missed them.

@jonathanstowe
Copy link
Contributor

For myself I am very excited by this, there is a fair amount of work-around in Tinky to stop it being impacted awaiting on lots of validators.

@jnthn
Copy link
Member Author

jnthn commented Jan 27, 2017

Feedback has been positive, and nobody has registered any objections, so I'll go ahead and merge this. It's low risk for existing code anyway, since you have to write use v6.d.PREVIEW to get the changed functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants