From: Ian Main Date: 2000-02-23T16:49:57-08:00 Subject: [ruby-talk:01551] Ruby thread scheduling buglet You're going to like this one :) The following program: ---- require "thread" N=4 def sitter(n) a = 0 while TRUE if (a.remainder (5000) == 0) printf ("thread %d at %d\n", n, a) end a += 1 end end def sleeper while TRUE sleep (0.01) end end for i in 0..N-1 Thread.start{sitter(i)} end Thread.start{sleeper} sleep ----- unexpectedly produces: thread 0 at 0 thread 0 at 5000 thread 0 at 10000 thread 1 at 0 thread 1 at 5000 thread 1 at 10000 thread 0 at 15000 thread 2 at 0 thread 2 at 5000 thread 2 at 10000 thread 1 at 15000 thread 1 at 20000 thread 0 at 20000 thread 0 at 25000 thread 0 at 30000 thread 3 at 0 thread 3 at 5000 thread 3 at 10000 thread 2 at 15000 thread 2 at 20000 thread 1 at 25000 thread 1 at 30000 thread 0 at 35000 thread 0 at 40000 thread 3 at 15000 thread 3 at 20000 thread 3 at 25000 thread 3 at 30000 thread 3 at 35000 thread 3 at 40000 ... (continuing on thread 3 for the rest of the programs life) I noticed this because the sleep () call is essentially what the gtk bindings are using, and you can't run more than one extra thread for them either. I think the reason is in rb_thread_schedule (): ... if (num_waiting_on_timer > 0) { now = timeofday(); FOREACH_THREAD_FROM(curr, th) { if (th->wait_for & WAIT_TIME) { if (th->delay <= now) { th->delay = 0.0; th->wait_for &= ~WAIT_TIME; th->status = THREAD_RUNNABLE; num_waiting_on_timer--; next = th; } else if (th->delay < delay) { delay = th->delay; } } } END_FOREACH_FROM(curr, th); } ... with the constant calling to sleep, it goes through this every call to rb_thread_schedule (). The thread that was sleeping, wakes up probably just about every run through this function, so its set as the current thread. It then loops about, goes to sleep again, and somewhere in there the next thread is run (thread 3 in our example), but then this one wakes up again before any others have a chance to run, and the scheduling is reset. I dunno what the perfect ruby-ish solution is so I'll leave that to you folk. Ian