from cofunctions import *
__all__ = ['run', 'schedule', 'coschedule', 'unschedule', 'block', 'unblock',
'run2', 'block_for_reading', 'block_for_writing', 'close_fd']
current = None
ready_list = []
names = {}
def names_of(seq):
return "[%s]" % ", ".join([names.get(g) for g in seq])
def schedule(g, name = None):
if name:
names[g] = name
ready_list.append(g)
def coschedule(f, *args, **kwds):
schedule(costart(f, *args, **kwds))
def unschedule(g):
if g in ready_list:
ready_list.remove(g)
@cofunction
def block(cocall, queue):
queue.append(current)
unschedule(current)
yield
def unblock(queue):
if queue:
g = queue.pop(0)
schedule(g)
def expire_timeslice(g):
if ready_list and ready_list[0] is g:
del ready_list[0]
ready_list.append(g)
def run():
global current
while ready_list:
g = ready_list[0]
current = g
try:
next(g)
except StopIteration:
unschedule(g)
else:
expire_timeslice(g)
class FdQueues:
def __init__(self):
self.readq = []
self.writeq = []
fd_queues = {}
def get_fd_queues(fd):
q = fd_queues.get(fd)
if not q:
q = FdQueues()
fd_queues[fd] = q
return q
@cofunction
def block_for_reading(cocall, fd):
yield cocall(block, get_fd_queues(fd).readq)
@cofunction
def block_for_writing(cocall, fd):
yield cocall(block, get_fd_queues(fd).writeq)
def close_fd(fd):
if fd in fd_queues:
del fd_queues[fd]
fd.close()
def wait_for_event():
from select import select
read_fds = []
write_fds = []
for fd, q in fd_queues.items():
if q.readq:
read_fds.append(fd)
if q.writeq:
write_fds.append(fd)
if not (read_fds or write_fds):
return False
read_fds, write_fds, _ = select(read_fds, write_fds, [])
for fd in read_fds:
unblock(fd_queues[fd].readq)
for fd in write_fds:
unblock(fd_queues[fd].writeq)
return True
def run2():
while 1:
run()
if not wait_for_event():
return