-
Notifications
You must be signed in to change notification settings - Fork 92
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
await() on already-completed future could return value synchronously #73
Comments
I agree this should be optimized. I'd suggest to do it within the main macro, though. Dropping the dependency on quasiquotes would be good to simplify the 2.10 build. |
I used a separate macro just as a feasibility test. If I have time I'll try to make a PR that changes the main macro. |
Ok, great. I'd be happy to review your PR if you have time. Thanks! |
@phaller, changing the main macro will make this a user-observable semantic change. Right now Is that desirable? Would it require updating SIP 22? |
Please comment, otherwise I won't work on the PR because I fear breaking the SIP-22 contract. |
I agree with you about avoiding semantic changes in the interface. This is what the API doc says about onComplete:
http://www.scala-lang.org/api/current/index.html#scala.concurrent.Future I tried to find if it is already done in the existing Futures' API and the closest I could get in the current implementation was this line: It seems to always run in the ExecutionContext, even if the Future is already completed, because this method is always called: |
Future.onComplete is much older and more widely used than scala-async, so I wouldn't propose such a change in behavior even if the API doc allowed it. But async/await is young enough to consider making even breaking changes. But since it's the official implementation of an accepted SIP, it would require another SIP to change (or whatever the amendment procedure is). So I'd like to know what the SIP guarantees. |
It is a pending SIP. We've still got some wiggle room to tweak these things. |
@gabriel-bezerra there's another reason why we can't change onComplete to be synchronous: it will cause code that calls onComplete in a loop to have stack overflows! The |
@retronym then I'll try to find time to make a PR changing the existing macro. |
This improves async/await to return synchronously if the future is already completed. See also scala/scala-async#73
Hi, On Android, where there is a significant distinction between the UI thread and all other threads, I use a Future {
// background work
} mapUi { r ⇒
// UI work
} Changing Regarding scala-async, I also use this pattern to ensure that all code between async {
// UI thread
await(...)
// still UI thread
await(...)
// UI thread again
}(UiThreadExecutionContext) Here the situation is a bit different, since a synchronous call to |
@stanch the proposed change is to make |
@danarmak Yes, that’s what I thought. Thanks for confirming. |
I tried to make the PR, but the code was much bigger and more complex than I expected. I'm afraid I won't have time to work on it, since the simple wrapper macro satisfies my own needs. If you're not going to do it yourselves, please feel free to close this ticket. |
I've encountered an interesting problem while using my The following code fails with a StackOverflowException:
The Commenting out the call to |
Actually, I just realized this has nothing to do with |
Good catch! I'd be interested to figure out how the C# translation of await/async avoids this. Perhaps we ought to detect if the next state transition is on the stack of previously visited states, and return from |
@retronym Fantastic. I just tested out the 0.9.3 snapshot and this little optimisation gives a significant performance improvement for my channels implementation (it often awaits on essentially Future.successful(x)). Over 3x faster on a sample test (410K messages/sec now compared to 120K messages/sec prior to the patch. Thanks! |
await(future) always compiles to future.onComplete(...), even if the future is already completed. (I think so based on the output of
scalac --Ymacro-debug-lite
in the 2.10 branch.) Why not return the value synchronously if it is already available?Here's a simple implementation as a macro wrapping await():
I have code that passes very large amounts of short-lived Futures around. Many of these are already completed when awaited. This optimization helps (from initial tests) and I'm considering using it in my code - is there any reason not to do this?
The text was updated successfully, but these errors were encountered: