4. Greenlet API
greenlet(func, parent=None): creates a greenlet to
run ‘func’
greenlet.switch(*args, **kw): switches execution to
the target greenlet, the first time
func(*args, **kw) will be executed
greenlet.throw([typ, [val, [tb]]]): switches execution
to the target greenlet and raises the specified
exception (GreenletExit by default)
6. How does it work?
Organized in a tree structure
Each greenlet has a ‘parent’, except main
When a greenlet dies, control is switched to its parent
Execution order isn’t always obvious
A glorified GOTO?!
7. How does it work? (II)
greenlet2
greenlet1
greenlet3
greenlet5
greenlet4
8. How does it work? (III)
‘Stack switching’
Non portable asm code
Copy stack slices on the heap
State is saved and restored when switching
CPU registers
Current Python frame, recursion depth and exception
state
9.
10.
11.
12.
13. Enter PyPy
New shiny and fast implementation of Python
Vast amount of fairy-dust covered unicorns
included
Includes an implementation of greenlet
Implemented on top of “continulet” objects
14. import _continuation
Continulets are one-shot continuations
Switching code is a standalone C library: stacklet
rpython/translator/c/src/stacklet/
15. Continulet API
continulet(func, *args, **kw): create a continulet
object which will call fun(cont, *args, **kw)
continulet.switch(value=None, to=None): start the
continulet or activate the previously suspended
one. If to is specified a ‘double switch’ is
performed
continulet.throw(type, value=None, tb=None,
to=None): similar to switch, but raise the given
exception after the switch is done
16. Stacklet
Tiny library implementing one-shot continuations
for C
Single C file (~400 lines) + per-platform asm
Supports x86, x86_64 and ARM
Nice and simple API
17. Stacklet API
stacklet_newthread(): creates a new thread handle
stacklet_new(thread_handle, run_func, run_arg):
calls run(arg) in a new stacklet, starts immediately
stacklet_switch(target): switches execution to
target stacklet
20. Using greenlet
Too low level, it’s usually used through a
framework
gevent, eventlet, evergreen *, gruvi *, ...
In these frameworks, switching happens through a
“hub”
*: these frameworks use python-fibers now
22. Undoing callbacks
import greenlet
# ...
def foo_async(cb):
call cb(result, error) eventually
pass
def foo_sync():
current = greenlet.getcurrent()
def cb(result, error):
if error is not None:
current.throw(Exception(error))
else:
current.switch(result)
foo_async(cb)
return hub.switch()
23. import fibers
shameless
plug!
Micro-threadling library API inspired by Python
threads and greenlet
Uses stacklet underneath
Works on CPython and PyPy
On PyPy it uses continulets
github.com/saghul/python-fibers
Or pip install fibers