Last active
May 17, 2016 15:38
-
-
Save jeremylowery/f37a48e7a702a628cc146eeb6ab8c8d3 to your computer and use it in GitHub Desktop.
Demonstration of using python generators as coroutines to implement cooperative multi-tasking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Demonstration of using python generators as coroutines to implement | |
cooperative multi-tasking. Catting multiple files in chunks to stdout. | |
There is room for much more generationization of operators, for example | |
implementing the yielding value as a Future. | |
Pass in a list of file names. | |
""" | |
import sys | |
import os | |
import select | |
MAX_BUF = 20 | |
def cat(fname): | |
fd = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) | |
while True: | |
line = yield fd | |
if not line: | |
break | |
print "%s:%r" % (fname, line) | |
def ioloop(): | |
# List of generators | |
running_cats = map(cat, sys.argv[1:]) | |
# map file descriptors to list of cats waiting on data | |
hungry_cats = {} | |
# food for the cats to eat. map generator worker to returned data | |
food = {} | |
while running_cats or hungry_cats: | |
feed_cats(running_cats, food, hungry_cats) | |
food = food_for(hungry_cats) | |
running_cats.extend(food.keys()) | |
def feed_cats(running, food, hungry): | |
# Let them run | |
while running: | |
c = running.pop() | |
try: | |
fd = c.send(food.pop(c, None)) | |
except StopIteration: | |
# Job Done | |
continue | |
hungry[fd] = c | |
def food_for(hungry_cats): | |
# See who is ready to wake up | |
food = {} | |
rlist, _, _ = select.select(hungry_cats.keys(), [], [], 0) | |
for fd in rlist: | |
data = os.read(fd, MAX_BUF) | |
food[hungry_cats.pop(fd)] = data | |
return food | |
ioloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment