Project

General

Profile

Feature #20102

Updated by ioquatix (Samuel Williams) 4 months ago

There are some tricky edge cases when using `Fibre#raise` and `Fiber#kill`, e.g. 

 ```ruby 
 fiber = nil 

 killer = Fiber.new do 
   
	 fiber.raise("Stop") 
 end 

 fiber = Fiber.new do 
   
	 killer.resume 
 end 

 fiber.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: 

 https://github.com/socketry/async/blob/ffd019d9c1d547926a28fe8f36bf7bfe91d8a168/lib/async/task.rb#L226-L233 

 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?`: 

 ```c 
 /* 
  *    call-seq: fiber.resumed? -> true or false 
  * 
  *    Whether the fiber is currently resumed. 
  */ 
 VALUE 
 rb_fiber_resuming_p(VALUE fiber_value) 
 { 
     struct rb_fiber_struct *fiber = fiber_ptr(fiber_value); 

     if (FIBER_TERMINATED_P(fiber)) return RUBY_Qfalse; 

     return RBOOL(fiber->resuming_fiber); 
 } 
 ``` 

 See the PR: https://github.com/ruby/ruby/pull/9382

Back