<div>Hi Arnar,</div>
<div>&nbsp;</div>
<div>Am I following io_operation right: the callback is an externally spawned (?) process which blocks waiting on the real IO operation but does not take up a slot in the Stackless round robin?&nbsp;And event.notify_when_ready_for_op returns instantly even if not ready? If so, then libevent seems to introduce a layer of multitasking that is not under the Stackless umbrella.</div>

<div>&nbsp;</div>
<div>The half-busy loop (with the time.sleep(0.0001)) is not necessary if the blocking select is used when no tasklets can run.</div>
<div>&nbsp;</div>
<div>The 1 ms and 2.5 ms were determined by experiment (you just loop on a usleep or nanosleep of some tiny positive amount - this always waits one tick, at least in C/Linux). This is obviously motherboard-dependent, and the newer motherboard had the slower response. I suspect interrupt response in general is getting sluggish, and they are afraid of a pileup of event code chained to the timer tick.</div>

<div>&nbsp;</div>
<div>Larry<br>&nbsp;</div>
<div><span class="gmail_quote">On 10/3/08, <b class="gmail_sendername">Arnar Birgisson</b> &lt;<a href="mailto:arnarbi@gmail.com">arnarbi@gmail.com</a>&gt; wrote:</span>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">Hi Larry,<br><br>On Fri, Oct 3, 2008 at 01:01, Larry Dickson &lt;<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>&gt; wrote:<br>
&gt; Wow! If that&#39;s your idea of a simple solution, I&#39;d hate to see a complicated<br>&gt; one ;-)<br><br>Well, if you look closely you&#39;ll see that it is basically a repeat of<br>the same pattern over and over:<br>
<br>def io_operation(*args,**kwargs):<br>&nbsp;&nbsp; def callback():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = perform_real_io_operation(*args,**kwargs)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; channel_dedicated_to_this_op.send(result)<br>&nbsp;&nbsp; event.notify_when_ready_for_op(callback)<br>
&nbsp;&nbsp; return channel_dedicated_to_this_op.receive()<br><br>This pattern is simply applied to file.read, file.write, socket.send,<br>socket.recv and socket.accept. The sleep function is even simpler.<br><br>As for the dispatching tasklet:<br>
<br>def _loop():<br>&nbsp;&nbsp;while _loop.running:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event.loop(True)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if stackless.getruncount() == 1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.0001)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stackless.schedule()<br>_loop.running = False<br><br>the time.sleep(0.0001) is simply an optimization in the case where<br>
there are no other tasklets runnable, in which case this would become<br>a busy loop eating 100% of cpu. You could leave it out and the<br>semantics would hold, in which case the loop is simply:<br><br>while running:<br>&nbsp;&nbsp; event.loop(True)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# dispatch any ready IO events<br>
&nbsp;&nbsp; stackless.schedule()&nbsp;&nbsp;# run other tasklets<br><br>&gt; Give me a week or so and I&#39;ll figure out how that works. What I do notice is<br>&gt; the time.sleep(0.0001) [by the way, I believe the minimum sleep is actually<br>
&gt; 1 ms in older PCs and 2.5 ms in newer PCs].<br><br>2.5 ms? That&#39;s ages.. do you have some references for this?<br><br>&gt; Unless C/Linux select is<br>&gt; designed horribly (and it could be), my second select approach gets an<br>
&gt; instant response as soon as the hard interrupt handler returns control to<br>&gt; the program. So my notion is not really reinventing the wheel - it is an<br>&gt; improvement. And it seems to me it is an awful lot simpler. The only danger<br>
&gt; - like any select - would be huge numbers of simultaneously waiting IOs.<br><br>Well, libevent uses the best available method on each platform, for<br>linux I believe it uses epoll and not select.<br><br>cheers,<br>Arnar<br>
</blockquote></div><br>