From mboxrd@z Thu Jan 1 00:00:00 1970 Message-Id: <200509271012.j8RACsT11583@zamenhof.cs.utwente.nl> To: Fans of the OS Plan 9 from Bell Labs <9fans@cse.psu.edu> Subject: Re: [9fans] thread confusion In-reply-to: Your message of "Mon, 26 Sep 2005 19:40:44 +0100." References: From: Axel Belinfante MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <11577.1127815973.1@zamenhof.cs.utwente.nl.cs.utwente.nl> Date: Tue, 27 Sep 2005 12:12:54 +0200 Topicbox-Message-UUID: 9161e40e-ead0-11e9-9d60-3106f5b1d025 > > I do use a timer, by having a proc that repeatedly sleeps > > and decrements a counter, and when the counter reaches > > zero it sends a (nil) timeout message on a channel. > > in alts I not only wait for the io channels but > > also for the timer timeout channel. > > > > the question is how to start and reset the timer. > > I have been thinking about using channels for that > > too, but that seems deadlock prone: how to avoid > > the case where I want to send a reset message to > > the timer when the timer wants to send an expiration > > message to me? > > i think this is a good question. > > i've found writing time-based code using the threads library to be > quite awkward. it seems to me that there may be room for an extension > to help with writing this kind of code. > > the difficulty with the plan 9 thread library (and with Limbo too) is > that sleep(2) exists in a different universe to channels, so one has > to use a separate process to bridge the gap. > > but when this thread is sleeping, it's not possible to communicate > with it, so one needs another thread to act as an intermediary, and > one has to design the interface carefully - if possible one doesn't > want a separate process and thread for each thread that wishes to wait > for a little while. I have seen the followup discussion after this post and like the idea of support for this in the thread library. Indeed the accuracy may/will be higher than what I'm using right now (but for my use it is not really an issue, I guess). This is just to share the approach I have taken after my initial posts on the topic. (after some bad experience) I've abandoned the idea of a timer process that only delivers expiration messages, and with which one communicates to start and cancel timers. Instead I'm using (something like) the etimer(2) approach. I have now a proc that regularly sends ticks over a channel using non-blocking sends, and decrement timers and check for expiration in the alt. Hmm... thinking on it while writing this, I suppose that tickproc could just as well use blocking sends. void tickproc(void *v) { for(;;) { sleep(tickTime); nbsend((Channel*)v, nil); } } use of ticks: ... t = ticksToWait; done = 0; while(!done) switch(alt(a)){ case iochannel: done = 1; ... other handling ... break; ... case tickchannel: t--; if (t == 0) { done = 1; ... handle timeout ... } } ... This seems to get the job done in a less complex and more clean way than what I was using before. Axel.