From: Robert Klemme Date: 2003-06-02T17:24:13+09:00 Subject: Re: thread-unsafe stuff: could you summarize? First, accesses to @deferRunning should be done synchronized. But: Why do you introduce @deferRunning when you have already a Mutex? You can do try_lock and locked? on a Mutex thread safe but without blocking the current thread. And: I have the feeling that in defer() a "not" is missing. Shouldn't it read def defer if not @deferRunning .... else .... end end Cheers robert "Tom Felker" schrieb im Newsbeitrag news:1054532088.2153.49.camel@tom.felker.net... > While you're asking that, I have a similar question: is the following > thread-safe? (This is part of PeerTalk, a LAN chat program I'm > writing.) > > ----- > =begin > defer.rb - the Defer module > > Defer is used to defer the execution of a block of code, to simplify > multi-threaded programming. Defer is useful when a GUI thread must be > the only thread that interacts with the toolkit, but other threads may > make demands on the GUI at any time. Defer can be mixed in to the GUI > class. > > To defer a block, call defer with the block. This can be done from > any thread, and defer will return immediately. When you are ready to > run the blocks, call run_deferred, which will execute the blocks in > the context of the calling thread (not the thread which defered them). > If a deferred block defers a block, that block will be executed > immediately, and the callback won't be called. > > To be notified when a block is deferred, call set_defer_callback with > an associated block. This block will be called whenever a block is > deferred, in the context of the thread defering it. You can use this > to notify the GUI thread that calling run_deferred is necessary. > > =end > > require "thread" > > module Defer > > def initialize > super > @deferBlocks = Queue.new > @deferRunning = false > @deferCallback = Proc.new { } > @deferMutex = Mutex.new > end > > def defer > if @deferRunning > yield > else > @deferBlocks.push Proc.new > @deferCallback.call > end > end > > def run_deferred > return if @deferRunning > @deferMutex.synchronize do > @deferRunning = true > begin > until @deferBlocks.empty? > @deferBlocks.pop.call > end > ensure > @deferRunning = false > end > end > end > > def set_defer_callback > @deferCallback = Proc.new > end > > end > > class Deferrer > include Defer > def initialize(*args) > super(*args) > end > end > > > > > -- > Tom Felker > > If we developed a replicator, it would be banned for its threat to > the profits of existing business. > >