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

Execute IO.blocking on WSTP without BlockContext indirection #3903

Merged
merged 9 commits into from
Jan 8, 2024

Conversation

armanbilge
Copy link
Member

We already have all the fantastic machinery to execute blocking code on a WorkerThread and it is pointless to indirect through the BlockContext interface when we can just invoke this mechanism directly.

@@ -797,7 +797,7 @@ private final class WorkerThread(
* There is no reason to enclose any code in a `try/catch` block because the only way this
* code path can be exercised is through `IO.delay`, which already handles exceptions.
*/
override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = {
def prepareBlocking(): Unit = {
val rnd = random

pool.notifyParked(rnd)
Copy link
Member Author

Choose a reason for hiding this comment

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

Unrelated, but I wonder why we invoke notifyParked() unconditionally, even if this thread is already blocking = true.

Copy link
Member

Choose a reason for hiding this comment

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

Good question. I'm guessing there's no reason and we can probably guard that notification as you say.

Comment on lines 495 to 497
if (worker.canExecuteBlockingCodeOn(this))
worker.prepareBlocking()
true
Copy link
Member

Choose a reason for hiding this comment

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

Can we move this logic up into IOFiber instead? I don't think there's any particular reason for it to be here, and you're making something that looks like a boolean check into a side-effecting method.

Copy link
Member Author

@armanbilge armanbilge Nov 24, 2023

Choose a reason for hiding this comment

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

Well conceptually I liked that if canExecuteBlockingCode() returns true then you can run blocking code, immediately.

I do see your point. We can expose this as a separate method which IOFiber calls. This requires:

  1. Doing the whole Thread.currentThread() dance a second time. How should we handle the case where the current thread is not a WorkerThread, or does not belong to the current pool? Do we care about those cases?

  2. Also exposing whatever new API we invent on the JS WorkStealingThreadPool shim. Not a big deal, just annoying.

Worth it?

Copy link
Member Author

@armanbilge armanbilge Nov 24, 2023

Choose a reason for hiding this comment

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

Oh lol, also I just realized this is bugged as-written 😅 fixed in c2ef8bc.

@@ -797,7 +797,7 @@ private final class WorkerThread(
* There is no reason to enclose any code in a `try/catch` block because the only way this
* code path can be exercised is through `IO.delay`, which already handles exceptions.
*/
override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = {
def prepareBlocking(): Unit = {
val rnd = random

pool.notifyParked(rnd)
Copy link
Member

Choose a reason for hiding this comment

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

Good question. I'm guessing there's no reason and we can probably guard that notification as you say.

djspiewak
djspiewak previously approved these changes Jan 8, 2024
@armanbilge armanbilge merged commit adc72fe into typelevel:series/3.5.x Jan 8, 2024
28 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants