Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!us.feeder.erje.net!feeder.erje.net!eu.feeder.erje.net!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Marko Rauhamaa Newsgroups: comp.lang.python Subject: Emperor's New Coroutines? Date: Mon, 07 Jul 2014 12:42:28 +0300 Organization: A noiseless patient Spider Lines: 74 Message-ID: <87lhs5h5dn.fsf@elektro.pacujo.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx05.eternal-september.org; posting-host="ff5cf27ef3d5b31f034d3b72bdc27a41"; logging-data="19847"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/7Gw+okLmcF7vXW4Ku/HbF" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) Cancel-Lock: sha1:Ejy4wt9MO0Uz7wwwmJdcY6z6EWc= sha1:D/iezLsHDsD2TJfxwRJnvzMRAcc= Xref: csiph.com comp.lang.python:74091 The asyncio module comes with coroutine support. Investigating the topic on the net reveals that FSM's are for old people and the brave new world uses coroutines. Unfortunately, all examples I could find seem to be overly simplistic, and I'm left thinking coroutines have few practical uses in network programming. PEP-380 refers to the classic Dining Philosophers: (reproduced below). Suppose I want to fix the protocol by supplying an "attendant" object that periodically tells the philosophers to drop whatever they are doing and start thinking. So I would add: schedule(attendant(..., [ plato, socrates, euclid ])) but how would I modify the philosopher code to support such master resets? Marko ======================================================================== from scheduler import * class Utensil: def __init__(self, id): self.id = id self.available = True self.queue = [] def acquire(self): #print "--- acquire", self.id, "avail", self.available if not self.available: block(self.queue) yield #print "--- acquired", self.id self.available = False def release(self): #print "--- release", self.id self.available = True unblock(self.queue) def philosopher(name, lifetime, think_time, eat_time, left_fork, right_fork): for i in range(lifetime): for j in range(think_time): print(name, "thinking") yield print(name, "waiting for fork", left_fork.id) yield from left_fork.acquire() print(name, "acquired fork", left_fork.id) print(name, "waiting for fork", right_fork.id) yield from right_fork.acquire() print(name, "acquired fork", right_fork.id) for j in range(eat_time): # They're Python philosophers, so they eat spam rather than spaghetti print(name, "eating spam") yield print(name, "releasing forks", left_fork.id, "and", right_fork.id) left_fork.release() right_fork.release() print(name, "leaving the table") forks = [Utensil(i) for i in range(3)] schedule(philosopher("Plato", 7, 2, 3, forks[0], forks[1]), "Plato") schedule(philosopher("Socrates", 8, 3, 1, forks[1], forks[2]), "Socrates") schedule(philosopher("Euclid", 5, 1, 4, forks[2], forks[0]), "Euclid") run()