Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Remove running on `EmptyCoroutineContext #307

Merged
merged 8 commits into from Nov 30, 2020
Merged

Conversation

nomisRev
Copy link
Member

Running tokens on EmptyCoroutineContext removes the CoroutineContext from the suspend program, and potentially makes us lose state. Instead we should always favor Unintercepted + coroutineContext/Continuation#context to run suspend code on current thread with existing CoroutineContext state.

@nomisRev nomisRev changed the title Remove running tokens on `EmptyCoroutineContext Remove running on `EmptyCoroutineContext Nov 27, 2020
Copy link
Member

@1Jajen1 1Jajen1 left a comment

Choose a reason for hiding this comment

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

This looks good to me, its a step forward to not loosing the context. This may have some unforeseen effects but so did the use of EmptyCoroutineContext and this is definitely better^^

*/
internal class ForwardCancellable {
internal class ForwardCancellable(private val ctx: CoroutineContext) {
Copy link
Member

Choose a reason for hiding this comment

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

Is this, or should this, be configurable in any way in the api of the methods using it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this could definitely be configurable. I'm still wondering a bit, since running cancel tokens on an IOPool is probably safest.

Now the're most likely to run on the default pool, but for the current usages I think this makes most sense. It's used in bracketCase and it's derived methods, and cancellable. It makes the release and CancelToken to be run with the same ctx as their use/acquire and f functions.

Copy link
Contributor

@danimontoya danimontoya left a comment

Choose a reason for hiding this comment

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

Neat 💯 !

timerConn
) { timeOut ->
// Launch timer on current thread (Unintercepted) with default ctx (sleep returns there), and timer connection
// Launch on current thread, since it will immediately fork to sleeper scheduler, and free current Thread
Copy link
Member

Choose a reason for hiding this comment

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

I don't get this part, aren't you launching below on the Computation pool thread and not the current one?

Copy link
Member Author

Choose a reason for hiding this comment

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

suspend { sleep(duration) } is started with startCoroutineUnintercepted which means it immediately starts running without getting intercepted() which means it won't get scheduled on ComputationPool.

However sleep requires a ContinuationInterceptor to be installed, otherwise, it cannot shift away from the sleep scheduler when it returns from sleeping. This is problematic since nothing is supposed to run on the scheduling sleep.

So by using startCoroutineUnintercepted and ComputationPool we can launch the sleeping fiber without first intercepting/scheduling, and we install ComputationPool as a ContinuationInterceptor for sleep to safely return there.

@nomisRev nomisRev merged commit 1c3092f into master Nov 30, 2020
@nomisRev nomisRev deleted the sv-revise-empty-context branch November 30, 2020 15:44
1Jajen1 added a commit that referenced this pull request Nov 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants