hemant
1/4/2007 3:48:00 AM
On Thu, 2007-01-04 at 07:15 +0900, Kenosis wrote:
> Hemant Kumar wrote:
> > On Thu, 2007-01-04 at 01:04 +0900, ara.t.howard@noaa.gov wrote:
> > > > Now, as someone suggested on IRC, I can do a join and wait for the
> > > > thread to finish. But the problem is, I don't exactly have an instance
> > > > to the thread, because its managed by a plugin and i am just using the
> > > > plugin to do stuff.
> > > >
> > > > Any ideas/suggestions are more than welcome.
> > >
> > > it seems that all you've managed to do is write a very long race condition.
> > > i'm not one of those people who think the mere mention of the word
> > > 'unit-testing' bestows any sort of robustness on code. for example, the
> > > testing of 'thread_status' in your test means nothing, as it's the source of
> > > the race condition: you need to wrap setting and reading this var with a
> > > semaphore. this shows why:
> > >
> > > harp:~ > cat a.rb
> > > class C
> > > attr :thread
> > > def initialize
> > > @thread = nil
> > > end
> > > def new_thread
> > > Thread.new{ @thread = Thread.current }
> > > end
> > > end
> > >
> > > 4242.times{|i| raise "race condition @ loopno #{ i }!" unless((c = C.new) and (Thread === c.new_thread) and c.thread) }
> > >
> > >
> > > harp:~ > ruby a.rb
> > > a.rb:11: race condition @ loopno 942! (RuntimeError)
> > > from a.rb:11
> > >
> > >
> >
> > Thanks for the insight Ara, although my class is singleton so i
> > shouldn't get the problem you have described above.
> >
> > However can you show me a code sample, that doesn't cause race condition
> > in above code. I tried using Mutex on above code,
> >
> > require "thread"
> > class C
> > attr :thread
> > def initialize
> > mutex = Mutex.new
> > mutex.lock
> > @thread = nil
> > mutex.unlock
> > end
> >
> > def new_thread
> > Thread.new{
> > mutex = Mutex.new
> > mutex.lock
> > @thread = Thread.current
> > mutex.unlock
> > }
> > end
> >
> > end
> >
> > 4242.times{|i| raise "race condition @ loopno #{ i }!" unless((c =
> > C.new) and (Thread === c.new_thread) and c.thread) }
> >
> > And I am still getting a race condition. Using MonitorMixin to signal
> > execution seems like an overkill to me in above code.
> >
> > So can you show me a way of making above code not race.
> >
> >
> > > regarding your specific question though, you need to verify that a thread is
> > > created and that it's status is running. even if you don't have a handle on
> > > the thread you can set things up in your unit test to get one. something like
> > >
> > > harp:~ > cat a.rb
> > > def tracking_threads &b
> > > before = Thread.list
> > > yield
> > > after = Thread.list
> > > return after - before
> > > end
> > >
> > > threads = tracking_threads{ 2.times{ Thread.new{ sleep } } }
> > >
> > > threads.each{|t| p t.status}
> > >
> > >
> > > harp:~ > ruby a.rb
> > > "sleep"
> > > "sleep"
> > >
> > >
> >
> > Cool thanks.
>
> Try removing the "mutex = Mutex.new" from "new_thread" That's causing a
> thread local mutex to be created that's only being used by that thread
> and none of the others, because they have their own mutex. The threads
> need to share the SAME mutex in order to enable mutual exclusion
> between them, ie, the mutex you create in initialize(). That said, us
> better understanding what you actually want to unit test would help us
> to help you.
>
> Cheers,
>
> Ken
>
Since We are calling new each time, even using instance variables won't
solve the race condition. I have even tried using class variables, and I
am still getting race condition.
Ara, please demonstrate how you would solve the race condition in above
shown code of yours?