-
Notifications
You must be signed in to change notification settings - Fork 529
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
Changes from 4 commits
b4ecd33
e4a30c5
9e8f282
de50142
c2ef8bc
444512f
bf03fb3
862b60c
0450001
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -776,7 +776,7 @@ private final class WorkerThread( | |
} | ||
|
||
/** | ||
* A mechanism for executing support code before executing a blocking action. | ||
* Support code that must be run before executing a blocking action on this thread. | ||
* | ||
* The current thread creates a replacement worker thread (or reuses a cached one) that will | ||
* take its place in the pool and does a complete transfer of ownership of the data structures | ||
|
@@ -797,16 +797,14 @@ 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated, but I wonder why we invoke There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
if (blocking) { | ||
// This `WorkerThread` is already inside an enclosing blocking region. | ||
// There is no need to spawn another `WorkerThread`. Instead, directly | ||
// execute the blocking action. | ||
thunk | ||
// This `WorkerThread` has already been prepared for blocking. | ||
// There is no need to spawn another `WorkerThread`. | ||
} else { | ||
// Spawn a new `WorkerThread` to take the place of this thread, as the | ||
// current thread prepares to execute a blocking action. | ||
|
@@ -819,7 +817,7 @@ private final class WorkerThread( | |
cedeBypass = null | ||
} | ||
|
||
// Logically enter the blocking region. | ||
// Logically become a blocking thread. | ||
blocking = true | ||
|
||
val prefix = pool.blockerThreadPrefix | ||
|
@@ -853,11 +851,17 @@ private final class WorkerThread( | |
pool.blockedWorkerThreadCounter.incrementAndGet() | ||
clone.start() | ||
} | ||
|
||
thunk | ||
} | ||
} | ||
|
||
/** | ||
* A mechanism for executing support code before executing a blocking action. | ||
*/ | ||
override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = { | ||
prepareBlocking() | ||
thunk | ||
} | ||
|
||
private[this] def init(newIdx: Int): Unit = { | ||
_index = newIdx | ||
queue = pool.localQueues(newIdx) | ||
|
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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()
returnstrue
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:Doing the whole
Thread.currentThread()
dance a second time. How should we handle the case where the current thread is not aWorkerThread
, or does not belong to the current pool? Do we care about those cases?Also exposing whatever new API we invent on the JS
WorkStealingThreadPool
shim. Not a big deal, just annoying.Worth it?
There was a problem hiding this comment.
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.