From: Robert Feldt Date: 2000-10-27T23:40:50+09:00 Subject: [ruby-talk:5916] Re: [RFC] Towards a new synchronisation primitive Continuing my previous message that was sent before complete... On Fri, 27 Oct 2000, hipster wrote: > > 4. Implement message queues and the rest of the common multi-threading > > helper classes in extension 'multithreading'. > > > > My knowledge of the current implementation of Ruby threads is somewhat > > limited though, so I'm not sure how this would affect the deadlock > > detection currently available? > > Same here. Got some catching up to do :\ > > IMO a good proposal, thanks. > Thanks for your feedback. Below is example code for Mutex and module Synchronized (using test_and_set), using test_and_set, so that you can do: class MySynchedClass include Synchronized def my_synched_method ... end synchronized :my_synched_method end It's only on the object level though. Finer granularity might be needed... I think it correctly handles Dave's RingBuffer example but I'm not sure. Can someone verify? class Mutex def initialize @waiting_threads = [] @locked = false # Not locked yet... @waiting_threads.taint # enable tainted comunication self.taint end # Since there is not yet a test_and_set in Ruby we use existing # Thread.critical= syntax. def test_and_set Thread.critical = true previous_value = @locked @locked = true Thread.critical = false previous_value end private :test_and_set def non_blocking_lock !test_and_set end alias try_lock non_blocking_lock def lock while test_and_set @waiting_threads.push Thread.current Thread.stop end self end def unlock return unless @locked # It's ok to release lock before releasing waiting thread # since Mutex do not garantuee an ordering of the threads. # Maybe we should supply different mutexes so that you can choose # the behavior you want (say BlockedQueueMutex that unlocks # threads FIFO-style, and BlockedSetMutex for the current impl?) @locked = false begin t = @waiting_threads.shift t.wakeup if t rescue ThreadError retry end self end # I can't see the use for exclusive_unlock but please enlighten me ;-) end # In the spirit of Masatoshi SEKI's MutexM: module Synchronized def Synchronized.append_features(klass) super # Add synchronized (for synchronizing on the object level) # Maybe have way to synch on method level? def klass.synchronized(*methods) for method in methods begin method = method.id2name rescue NameError end old = "_old_#{method}" # We need something smarter here to handle methods including any of the characters [,] or =. Counter in class var? module_eval("alias #{old} #{method}") module_eval("def #{method}(*a,&b); @m.lock; #{old}(*a,&b); @m.unlock; end") private(old) end end return self end private def initialize(*args) ret = super # We should probably extend this to have locks/mutexes on finer granularity # so that you can sync on the instance mutex or on individual methods # mutexes? Is it needed? If so we can generate the mutex initialization # code below dynamically? @m = Mutex.new return ret end end Regards, Robert