Emperor's New Coroutines?

Marko Rauhamaa marko at pacujo.net
Mon Jul 7 11:42:28 CEST 2014


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: <URL: http://www.cos
c.canterbury.ac.nz/greg.ewing/python/yield-from/yf_current/Examples/Sch
eduler/philosophers.py> (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()



More information about the Python-list mailing list