-
Notifications
You must be signed in to change notification settings - Fork 530
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
Add IO.unyielding
#2633
Add IO.unyielding
#2633
Conversation
Thanks for the PR, and all your contributions! Apologies for the delayed response, tbh at least for me personally I still haven't quite wrapped my head around how to make this change. This is an ambitious one 😅 still, here are some comments.
Yes. This is illustrated in #2610 as a sort of "law": unyielding(cede) <-> unyielding(unit) Whether it can actually be implemented as a meaningful law, I'm not sure. In any case, we'll eventually want to add
I could be mistaken, but I don't think that was a goal of unyielding. I don't see why it should affect I took a brief look at your changes and they seem to be on the right track. But, we'll need a runloop expert to comment on that :) also I think there's some interesting questions here about how to handle the autocede counter during an |
Thank you @armanbilge for looking over the PR. I'm aware that there is still a lot of improvement to be made to this PR, so any suggestion is more than welcome 😄 (thank you for the
I've thought that using |
Ah, thanks for clarifying! Maybe there is some confusion here, depending on how you define "shifting" 🤔 So if we adjust your example program a bit, I think we can start to see the behavior: for { // fiber A
_ <- IO(println("foo")
_ <- IO(println("bar").start // fiber B
_ <- IO.cede // fiber A yields, so fiber `B` runs now
_ <- IO(println("baz")
} yield () As written, I think this program should get you |
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.
Finally got to this!
Okay so I have two concerns right now. First, I don't like how the name is asymmetrical with cede
. But unceding
sounds dumb. :-) Second, and more concerningly, I'm worried that people are going to write code which uses this function as more than just a hint. Even some basic examples like cachedRealTime
would need this function to behave exactly as implemented on IO
in order to function correctly, and that's concerning because we have to make the GenSpawn
implementation simply identity. I don't really know how to avoid this issue, though.
@@ -92,6 +92,7 @@ private final class IOFiber[A]( | |||
|
|||
private[this] var canceled: Boolean = false | |||
private[this] var masks: Int = 0 | |||
private[this] var unyield: Boolean = false |
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.
I'm pretty sure this needs to be an Int
rather than a Boolean
. The problem is that you want IO.unyielding(IO.unyielding(IO.unit) *> IO.cede)
to suppress the cede
.
Moving this out to v3.5.0 in the interest of being cautious, since we're making a change to the axioms in a meaningful sense. |
Sorry for being quiet for such a long time. I'm not sure when I'll be able to pick this up again in the near future, sorry for that. In the meantime, if someone is interested to pick this up, I'm more than happy to share 😄 |
It's quite alright! This is a surprisingly thorny one. A lot of the work that needs to be done here is just discussion and analysis. I'm really not convinced that any one direction is better than another so it needs some thought. |
So I've spent a few months mulling on this, and while I very much want to add it, I can't see a way of doing so without binary breakage. Or rather, we can add it without binary breakage, but the result will be silent semantic failures in a lot of cases. The whole point of this kind of construct is so that people can rely on it, and the failure modes are very much nondeterministic and difficult to discover. I think that we push the general version of this back to a future CE4. We could explore a version which is specific to Thank you so much for your work on it, @alexandrustana! I know it probably feels fruitless but honestly this was immensely helpful in exploring the space and trying to figure out what best to do. |
The following PR tries to fix #2610
I'm not really sure what I'm doing here 😅 if this is utter garbage please feel free to close it.
As I've understood from #2478 and #2530, the
unyielding
method should prevent a section of code from yielding (automatically or manually viacede
). The examples from the mentioned issues also show that usingstart
in anunyielding
block should prevent fiber scheduling.Running the following code snippet with the current changes:
generates the following result:
If this is indeed the intended behaviour, my question is if the
unyielding
block should also affectevalOn
orblocking
?