Feature #16792

Updated by Eregon (Benoit Daloze) about 2 years ago

Currently, Mutex in CRuby is held per Thread. 
 In JRuby and TruffleRuby, Mutex is held per Fiber (because it's simply easier implementation-wise). 

 While a user could theoretically notice the difference, it seems extremely uncommon in practice (probably incorrect synchronization). 

 The usage pattern for a Mutex is using #synchronize or lock+unlock. 
 Such a pattern protects/surrounds a region of code using some resource, and such a region of code is always on the same Fiber since it's on a given Ruby "stack". 

 With #16786 it becomes more relevant to have Mutex held per Fiber, otherwise Mutex#lock will basically would hurt scalability of that proposal significantly. 
 This means, if a Fiber does Mutex#lock and it's already held by another Fiber of the same Thread, and the Thread#scheduler is enabled, instead of just raising an error (which made sense before, because it would be a deadlock, but no longer the case with scheduler), 
 error, or preventing switching entirely until #unlock (current state in #16786, makes Mutex#lock special and hurts scalability), 
 #unlock, we would just go to the scheduler and schedule another Fiber (for instance, the one holding that Mutex, or any other ready to be run Fiber). 

 This is not a new idea and in fact Crystal already does this with its non-blocking Fibers, which is very similar with #16786: 

 Mutex#lock is just like other blocking operations, so let's make it so building on #16786. 
 I believe it's the natural and intuitive thing to do for Fiber concurrency with a scheduler. 

 Queue#pop and SizedQueue#push could be other candidates to handle in a similar way. 

 Here is an early commit to make Mutex held per Fiber, it's quite trivial as you can see: 
 It passes test-all and test-spec.