There are some tricky edge cases when using Fibre#raise and Fiber#kill, e.g.
fiber=nilkiller=Fiber.newdofiber.raise("Stop")endfiber=Fiber.newdokiller.resumeendfiber.resume# 4:in `raise': attempt to raise a resuming fiber (FiberError)# 4:in `block in <main>'
Async has to deal with this edge case explicitly by rescuing the exception:
I'd like to avoid doing that and instead just ask "Can I kill/raise on this fiber right now?" which is determined by whether the fiber itself can be resumed or transferred to.
To address this, I'd like to introduce Fiber#resuming?:
/*
* call-seq: fiber.resumed? -> true or false
*
* Whether the fiber is currently resumed.
*/VALUErb_fiber_resuming_p(VALUEfiber_value){structrb_fiber_struct*fiber=fiber_ptr(fiber_value);if(FIBER_TERMINATED_P(fiber))returnRUBY_Qfalse;returnRBOOL(fiber->resuming_fiber);}
Could you make it raise FiberError if it's called on a Fiber of a different thread?
Because that's always racy (i.e. it might have changed by the time resuming? returns) so it seems wrong to query that for a Fiber belonging to another thread.
@Eregon (Benoit Daloze) I appreciate your input. I don't mind doing that, but isn't that the same for all methods on Fiber? In other words, the GVL provides a bit of a safety net.
Should we apply this model to other methods? Maybe we need to define what methods can be called safely from one thread or another.
What about if a user has a mutex to control access, or the fiber/thread is not actually running at the time of the call?
I assume there is a lot of historical context/implementation where such behaviour is just racy but nothing is done to protect it.
In other words, I feel like the problem you are trying to address spans almost all of Ruby's mutable state... tricky.
@Eregon (Benoit Daloze) I appreciate your input. I don't mind doing that, but isn't that the same for all methods on Fiber?
It is, and many methods on Fiber are already not allowed to be called for Fibers belonging to other threads (e.g. resume/transfer/storage/...).
Since we are adding a new method, we might as well encourage correct usage and discourage incorrect usage (+ it means the state for resuming does not need to become volatile which would be bad for performance).
In other words, the GVL provides a bit of a safety net.
It does not, the GVL could be released e.g. just after resuming? is done but before the caller gets the value and handle it.
It appears to me that the method you want is to determine if an exception can legitimately be sent to the fiber. I am not rejecting the addition of such a method, but in that case, I think the name resuming? would be inappropriate. Any other name candidate?