[Stackless] gevent

Denis Bilenko denis.bilenko at gmail.com
Sat Nov 14 06:06:01 CET 2009

On Sat, Nov 14, 2009 at 12:43 AM, Richard Tew <richard.m.tew at gmail.com> wrote:
> It would certainly benefit Stackless, as People would of course be
> able to use wide swathes of the standard library and have their
> tasklets block nicely.
>> There are a couple of things I don't quite understand though.
>> 1. Will gevent on stackless take advantage of faster "soft" switching?
>> From reading this explanation by Kristján Valur Jónsson
>>  > 'hard switching' occurs when it becomes necessary to save the C
>> stack, and manipulate the stack pointer.
>>  > Usually this is because some C code has been involved in the
>> tasklet, so that its state cannot be fully
>>  > represented by just a linked chain of python frames.  For example,
>> if python code calls some C function
>>  > which then recursively calls into python.
>>  http://www.stackless.com/pipermail/stackless/2009-September/004271.html
>> it seems that it will not. That is because all switching is
>> orchestrated by the libevent event loop which is C code.
> I looked for the event loop the other day, but couldn't find it, can
> you give me a pointer to it?

The event loop is implemented by libevent's event_dispatch() which is wrapped
as gevent.core.dispatch() which is called by the Hub - a greenlet that
"owns" event loop.

This Hub greenlet does nothing else than running the event loop. Other greenlets
switch to it when they want to block. Before switching, a greenlet sets up
an event that will wake it up, that is, switch back to it. See the
example below.

>> 3. Is it possible to do switching directly in Stackless, in a manner
>> similar to greenlet's switch() and throw() methods?
>> I guess I could emulate greenlet's interface with Tasklet + Channel,
>> but that seems like an overkill.
> I am not sure what you need.  Can you give some context where you do
> this with greenlet?

Here's how gevent implements blocking socket.recv method:

   def recv(self, *args):
        if self.timeout!=0.0:
            wait_read(self.fileno(), timeout=self.timeout, timeout_exc=timeout)
        res = self.fd.recv(*args)
        return res

wait_read() blocks the greenlet until self.fileno() is readable or
timeout expires.
The full code you can see there:

The simplified version (without the timeout and extra check that the
switch is valid) is here:

def wait_read(fileno):
    evt = core.read_event(fileno, getcurrent().switch)

core.read_event is a wrapper around libevent's event and accepts
 - file descriptor to watch
 - callback to call

core.read_event() sets up a new event, then wait_read() switches to
the Hub, which was
running the event loop. It continues to run the event loop. Once
fileno become readable it
calls the callback, which switches to the original greenlet.
That way the greenlet appeared blocking while the event loop and other
greenlets were running.

So, that's how greenlet's switch() and throw() methods are used in gevent.
The question was are such methods available in Stackless or they have
to be emulated
(I guess by attaching a Channel to every Tasklet).

More information about the Stackless mailing list