Module: cogen
This is a library for network oriented, coroutine based programming. The interfaces and events/operations aim to mimic some of the regular thread and socket features.
cogen uses the enhanced generators in python 2.5. These generators are bidirectional: they allow to pass values in and out of the generator. The whole framework is based on this.
The generator yields a Operation instance and will receive the result from that yield when the operation is ready.
Roughly the cogen internals works like this:
+------------------------+
| @coroutine |
| def foo(): |
| ... | op.process(sched, coro)
| +->result = yield op--|----------------+------------+
| | ... | | |
+--|---------------------+ +---------------+ +---------------------+
| | the operation | | the operation can't |
result = op.finalize() | is ready | | complete right now |
| +------|--------+ +----------|----------+
scheduler runs foo | |
| | |
foo gets in the active | |
coroutines queue | |
| | |
+----------------------<----------+ |
| depening on the op
op.run() +---------+
| socket is ready add it in | |
+-------------<------------ ...... the reactor <--+ |
| later |
+------<------------------- ...... add it in some other <-+
some event decides queue for later run
this op is ready
The scheduler basicaly does 3 things:
- runs active (coroutine,operations) pairs (calls process on the op)
- runs the reactor
- checks for timeouts
The reactor basicaly does 2 things:
- calls the system to check what descriptors are ready
- runs the operations that have ready descriptors
The operation does most of the work (via the process, finalize, cleanup,
run methods):
- adds itself in the reactor (if it's a socket operation)
- adds itself in some structure to be activated later by some other event
- adds itself and the coro in the scheduler's active coroutines queue
The coroutine decorator wrappes foo in a Coroutine class that does some
niceties like exception handling, getting the result from finalize() etc.
Modules
common
A module for quick importing the essential core stuff. (coroutine, Scheduler, events, sockets, priority)
core
This module holds the essential stuff.
Programming with this library should be straghtforward. A coroutine is just a generator wrapped in a operation handling class:
@coroutine def mycoro(bla): yield <operation> yield <operation>
- the operation instructs the scheduler what to do with the coroutine: suspend it till someting happens, add another coro in the scheduler, raise a event and so on.
- the operations are split up in 2 modules: events and sockets
- the operations from sockets are related to network, like reading and writing, and these are done asynchronously but your code in the coroutine will see them as a regular synchronous or blocking call.
- the operations from events are related to signals and coroutine/scheduler management.
- if a operation has a result associated then the yield will return that result (eg. a string or a (connection, address) tuple) otherwise it will return the operation instance.
Typical example:
import sys, os from cogen.common import * @coroutine def server(): srv = sockets.Socket() srv.setblocking(0) srv.bind(('localhost',777)) srv.listen(10) while 1: print "Listening..." conn, addr = yield sockets.Accept(srv) print "Connection from %s:%s" % addr m.add(handler, conn, addr) @coroutine def handler(sock, addr): yield sockets.Write(sock, "WELCOME TO ECHO SERVER !\r\n") while 1: line = yield sockets.ReadLine(sock, 8192) if line.strip() == 'exit': yield sockets.Write(sock, "GOOD BYE") sock.close() return yield sockets.Write(sock, line) m = Scheduler() m.add(server) m.run()
web
This module holds a wsgi server and future web-related code.