The following sections contain an explanation of the design of the different parts that compose evergreen. Evergreen was inspired by similar libraries such as Gevent and Eventlet, but some of the key ideas are different:
The event loop can be considered the central point of evergreen, it deals with timers, I/O and task scheduling (described later). The event loop API is heavily inspired by PEP 3156, so it’s possible that in the future the event loop implementation evergreen uses can be replaced. At the moment evergreen uses puyv as the underlying event loop.
In evergreen only one loop may exist per thread, and it has to be manually created for threads other than the main thread. This would be the structure of a normal program using evergreen:
import evergreen
# Create the global loop
loop = evergreen.EventLoop()
# Setup tasks
...
# Start the loop
loop.run()
No tasks will start working until loop.run is called unless a blocking operation is performed, in which case the loop is automatically started. For long running processes such as servers, it’s advised to explicitly create the event loop, setup tasks and manually run it. Small scripts can rely on the fact that the main thread’s loop is automatically created and run when an opperation cooperatively blocks.
The cooperative task abstraction provided by evergreen (through the Task class). The public API for this class mimics that of a threading.Thread thread, but it’s scheduled cooperatively.
Tasks are implemented using the fibers library.
Here are some ‘rules’ that apply to tasks:
The scheduler has no public interface. You interact with it by switching execution to the loop. In fact, there is no single object representing the scheduler, its behavior is implemented by the Task, Future and other classes using only the public interface of the event loop.
The easiest way to suspend the execution of the current task and yield control to the loop so that other tasks can run is to use:
evergreen.sleep(0)
The only functions that suspend the current task are those which ‘block’, for example lock or socket functions.