I share that opinion. But, I'm wondering if there are cases where you have a lot of flatmapped actions stacked up on each other in a gigantic IO program, and you know you would like to yield every once in a while, but it's hard to inject that into your code because it's not really clear where those points actually are.
That's the concern exactly. In practice I've found this is rare to the point of non-existent, but I imagine it could happen. The only times I've been bitten by lack of fairness, it was my own fault and relatively easy to fix. If you think about what has to happen for a long series of CPU-hogging code to avoid any async boundaries at all, it usually requires a ton of pure compute code (so, you're doing
map with some
f which is expensive but pure). In that case, it doesn't matter whether your semantics are auto-yielding or not: it's going to hog the thread.
For there to be code which can be more fairness-optimized by some mechanism in the effect type, but isn't already so optimized, you need a ton of
delay actions bound together with
flatMaps. A ton of them. Without any
async in between and without any
shifts to other pools. That… happens… very very very rarely.
Which is to say that auto-yielding isn't as helpful as it sounds in practice. Certainly still meaningful, but more meaningful on paper than in reality.
If I use Async.async() inside of Resource.use(), I need to ensure myself that somehow the async operation is completed prior to the resource's release method is called
use method will not be called until (at least!) the callback inside of
async is run. Which is to say, you have control over it. Remember that
async doesn't mean "parallel", it just means non-blocking.
R. Within the
usemethod I use Async.async() on
R(so the callback necessarily has to be called after the
usemethod). Assuming I am not altering ExecutionContexts or ContextShifts, is it possible for the
releasemethod to be called prior to the callback finishing if I do not explicitly synchronize this?
use, not after
start, then you have a problem
async, you will be safe
asyncyou see it
A => Unit
foo = bar(a)becomes
bar(a, foo => everythingElse)
bar(a: A, logicalReturn: A => Unit) = ...., logicalReturn(result)