In article <200705160759.l4G7x8Tr014065 / sharui.nakada.kanuma.tochigi.jp>, Nobuyoshi Nakada <nobu / ruby-lang.org> wrote: >Hi, > >At Wed, 16 May 2007 15:40:08 +0900, > >=46rom where is this function called? Unless it's called as a >ruby method, you can't use rb_yield() in it. You might assume >the block to bmidi_each() is accessible, it is never guaranteed >at all. Yes, I realize this now. [In fact I realized it during my last post, saw the real solution, started to report that, then started thinking it was *still* wrong, and erased it! On the way to bed it dawned on me it was correct after all.] I was being fooled a bit by the PickAxe 'jukebox' example, which uses a callback from external code, but of course he assumes everything is single-threaded, so that the callback *does* derive from a ruby call somewhere back up the call chain. > > >Since bmidi_ensure() won't get called until bmidi_doeach() >ends, the latter seems to success to acquire the semaphore only >when the callback released it. At that time, the callback sets >receiving to false before the release, so the bmidi_ensure() >leaves the semaphore locked which acquired by bmidi_doeach(), I >guess. In short, the sequence is wrong. Actually, no. I think that part is correct. The callback only releases the semaphore *if* the yield signals termination. The idea of the ensure was to release the semaphore if the callback hadn't -- i.e. if break bypassed the yield. > >Anyway, you need to call rb_yield() in bmidi_each(). *This* is the key. I was sort of thinking in the OS's framework, not Ruby's. At first I didn't think I could have the yield there, but I realize that I can rearrange the semaphoring to synchronize the two (OS) threads, and keep everything nice and orderly. Thanks for your help -- Pete -- -- ============================================================================ The address in the header is a Spam Bucket -- don't bother replying to it... (If you do need to email, replace the account name with my true name.)