In article <[EMAIL PROTECTED]>, Rocco Caputo <[EMAIL PROTECTED]> writes: > The event loop libraries may require Ugly Workarounds to behave > properly. Tk, for example, will starve I/O watchers if you start a > 0ms after() timer from a timer callback. In your example, the > recursive yield() would prevent select_read() from ever seeing > activity on the pipe. > Ah, so yield is dispatched as a period 0 alarm in under Tk. And the alarm starvation workaround just happens to work like this ? Ok.
By the way, in my tests with Tk short alarms can't totally starve other events, they just seem to have a too high priority. #!/usr/bin/perl -w use Tk qw(DONT_WAIT WINDOW_EVENTS FILE_EVENTS DoOneEvent MainLoop); my $w = Tk::MainWindow->new(); my $acount = 0; my $rcount = 0; my $count = 0; sub endp { return unless ++$count >= 300; print "alarm: $acount, readable: $rcount\n"; exit; } sub acount { $w->after(0, \&acount); $acount++; endp(); } $w->after(0, \&acount); pipe(local *RD, local *WR) || die "Pipe: $!"; close WR; $w->fileevent(\*RD, "readable", sub { $rcount++; endp(); }); MainLoop; This outputs alarm: 200, readable: 100 Or you can replace MainLoop by (skipping the Tk::MainWindow->Count test): DoOneEvent(DONT_WAIT | WINDOW_EVENTS | FILE_EVENTS) while DoOneEvent(); In which case you'd get the more reasonable: alarm: 150, readable: 150 But maybe that's different in different Tk version. > Whew. Now, to solve your problem. > > It might be more reliable to use small delays, perhaps on the order of > 1/100 second, to detect idleness. It also might be more efficient, as > actual work will have precedence over the idleness polling loop. > This is a not a bad idea. Idleness detection will work a bit slower, but it will stress the system less so idleness might actually be reached sooner. I just wish there was some portable way to decide on a minimum time argument where I can be sure it won't get rounded down to 0. The main problem is that if there ever is an event source (like a periodic alarm or regularly arriving packets) that happens more often than the idle timeout, idleness will never be triggered even though the CPU time for it may well be available. > In tests, replacing yield("yielder") with delay("yielder", 0.01) > results in (Tk) output like: > ... > yielder > readable <-- potential problem > yielder ... > The potential problems are cases where we almost falsely detected > idleness. A higher delay value might help. > I suspect the problem actually can't happen after maybe a first startup exception, but that's again depending too much on internals :-) For the moment I think I will just keep using a busy yield loop and just live with the occasional extra trigger of idleness. Or you could consider adding an "idle" to POE. Tk and Event both directly support it, and it's easy to add to self-written eventloops :-)