\chapter{Python Iterators and Generators}
\label{chap:itergen}

Here is where Python begins to acquire further abstraction.  Though I
generally am not a fan of having a lot of abstraction, the constructs
here are both elegant and useful.  In the case of generators in
particular, it's more than just abstraction; it actually enables us to
do some things that essentially could not otherwise be done.

\section{Iterators}

\subsection{What Are Iterators?  Why Use Them?} 

Let's start with an example we know from Chapter \ref{chap:filedir}.
Say we open a file and assign the result to {\bf f}, e.g.

\begin{Verbatim}[fontsize=\relsize{-2}]
f = open('x')
\end{Verbatim}

Suppose we wish to print out the lengths of the lines of the file.  

\begin{Verbatim}[fontsize=\relsize{-2}]
for l in f.readlines(): 
   print len(l)
\end{Verbatim}

But the same result can be obtained with

\begin{Verbatim}[fontsize=\relsize{-2}]
for l in f: 
   print len(l)
\end{Verbatim}

The second method has two advantages:

\begin{itemize}

\item [(a)] it's simpler and more elegant

\item [(b)] a line of the file is not read until it is actually needed

\end{itemize}

For point (b), note that typically this becomes a major issue if we are
reading a huge file, one that either might not fit into even virtual
memory space, or is big enough to cause performance issues, e.g.
excessive paging.

Point (a) becomes even clearer if we take the functional programming
approach.  The code

\begin{Verbatim}[fontsize=\relsize{-2}]
print map(len,f.readlines())
\end{Verbatim}

is not as nice as

\begin{Verbatim}[fontsize=\relsize{-2}]
print map(len,f)
\end{Verbatim}

As noted,
Point (b) would be of major importance if the file were really large.
The first method above would have the entire file in memory, very
undesirable.  Here we read just one line of the file at a time.  Of
course, we also could do this by calling {\bf readline()} instead of
{\bf readlines()}, but not as simply and elegantly, e.g. we could not
use {\bf map()}.

In our second method above, 

\begin{Verbatim}[fontsize=\relsize{-2}]
for l in f: 
   print len(l)
\end{Verbatim}

{\bf f} is serving as an {\bf iterator}.  Let's look at the concept more
generally.  

Recall that a Python {\bf sequence} is roughly like an array in most
languages, and takes on two forms---lists and tuples.\footnote{Recall
also that strings are tuples, but with extra properties.}  Sequence
operations in Python are much more flexible than in a language like C or
C++.  One can have a function return a sequence; one can {\bf slice} 
sequences; one can concatenate sequences; etc.

In this context, an {\bf iterator} looks like a sequence when you use
it, but with some major differences.  With an iterator,

\begin{itemize}

\item [(a)] you usually must write a function which actually constructs
that sequence-like object

\item [(b)] an element of the ``sequence'' is not actually produced
until you need it

\item [(c)] unlike real sequences, an iterator ``sequence'' can be
(in concept) infinitely long
\end{itemize}

\subsection{Example:  Fibonacci Numbers}
\label{fibitr}

For simplicity, let's start with everyone's favorite computer science
example, Fibonacci numbers, as defined by the recursion,

\begin{equation}
f_n = \cases{
1, & if $n = 1,2$ \cr
f_{n-1}+f_{n-2}, & if $n > 2$ \cr
}
\end{equation}

It's easy to write a loop to compute these numbers.  But let's try it
as an iterator:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# iterator example; uses Fibonacci numbers, so common in computer
# science examples:  f_n = f_{n-1} + f_{n-2}, with f_0 = f_1 = 1

class fibnum:
   def __init__(self):
      self.fn2 = 1  # "f_{n-2}"
      self.fn1 = 1  # "f_{n-1}"
   def next(self):  # next() is the heart of any iterator
      # note the use of the following tuple to not only save lines of
      # code but also to insure that only the old values of self.fn1 and 
      # self.fn2 are used in assigning the new values
      (self.fn1,self.fn2,oldfn2) = (self.fn1+self.fn2,self.fn1,self.fn2)
      return oldfn2
   def __iter__(self):
      return self
\end{Verbatim}

Now here is how we would use the iterator, e.g. to loop with it:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
from fib import *

def main():
   f = fibnum()
   for i in f:
      print i
      if i > 20: break

if __name__ == '__main__':
   main()
\end{Verbatim}

By including the method {\bf \_\_iter\_\_()} in our {\bf fibnum} class,
we informed the Python interpreter that we wish to use this class as an
iterator.  

We also had to include the method {\bf next()}, which as its name
implies, is the mechanism by which the ``sequence'' is formed, the
mechanism to produce the ``next'' item.  This enabled us to simply place
an instance of the class in the {\bf for} loop above.  Knowing that {\bf
f} is an iterator, the Python interpreter will repeatedly call {\bf
f.next()}, assigning the values returned by that function to {\bf i}.
When there are no items left in the iterator, a call to next produces
the {\bf StopIteration} exception.

% It returns itself (in this common but not exhaustive form), which is
% used for iteration in {\bf for} loops.

\subsection{The iter() Function}

Some Python structures already have built-in iterator capabilities.
For example, 

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__',
'__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__',
'__setslice__', '__str__', 'append', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
\end{Verbatim}

As you can see, the Python's {\bf list} class includes a member function
{\bf \_\_iter\_\_()}, so we can make an iterator out of it.  Python
provides the function {\bf iter()} for this purpose, e.g.:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> i = iter(range(5))
>>> i.next()
0
>>> i.next()
1
\end{Verbatim}

Though the {\bf next()} function didn't show up in the listing above, it
is in fact present:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> i.next
<method-wrapper 'next' of listiterator object at 0xb765f52c>
\end{Verbatim}

You can now understand what is happening internally in this
innocent-looking {\bf for} loop:

\begin{Verbatim}[fontsize=\relsize{-2}]
for i in range(8): print i
\end{Verbatim}

Internally, it's doing

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
itr = iter(range(8))
while True:
   try:
      i = itr.next()
      print i 
   except:
      raise StopIteration
\end{Verbatim}

Of course it is doing the same thing for iterators that we construct
from our own classes.

You can apply {\bf iter()} to any sequence, e.g.:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> s = iter('UC Davis')
>>> s.next()
'U'
>>> s.next()
'C'
\end{Verbatim}

and even to dictionaries, where the iterator returns the keys.

You can also use {\bf iter()} on any callable object.

\subsection{Applications to Situations with an Indefinite Number of
Iterations}

As stated above, the iterator approach often makes for more elegant
code.  But again, note the importance of not having to compute the
entire sequence at once.  Having the entire sequence in memory would
waste memory and would be impossible in the case of an infinite
sequence, as we have in the Fibonacci numbers example.  Our {\bf for}
loop above is iterating through an infinite number of iterations---and
would do so, if we didn't stop it as we did.  But each element of the
``sequence'' is computed only at the time it is needed.

Moreover, this may be necessary, not just a luxury, even in the finite
case.  Consider this simple client/server pair in the next section.

\subsubsection{Client/Server Example}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# x.py, server

import socket,sys,os

def main():
   ls = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
   port = int(sys.argv[1])
   ls.bind(('', port))
   ls.listen(1)
   (conn, addr) = ls.accept()
   while 1:
      l = raw_input() + '\n'  # raw_input() doesn't give an '\n
      conn.send(l)

if __name__ == '__main__':
   main()
\end{Verbatim}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# w.py, client

import socket,sys

def main():
   s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   host = sys.argv[1]  
   port = int(sys.argv[2])  
   s.connect((host,port))
   flo = s.makefile('r',0)  # file-like object, thus iterable
   for l in flo:
      print l[:-1]

if __name__ == '__main__':
   main()
\end{Verbatim}

The server reads lines from the keyboard.  It sends each line to the
client as soon as the line is typed.  However, if on the client side we
had written

\begin{Verbatim}[fontsize=\relsize{-2}]
   for l in flo.readlines:
      print l
\end{Verbatim}

instead of

\begin{Verbatim}[fontsize=\relsize{-2}]
   for l in flo:
      print l

\end{Verbatim}

then the client would print out nothing until all of {\bf flo} is
received, meaning that the user on the server end typed ctrl-d to end
the keyboard input, thus closing the connection.

Rather than being thought of as an ``accident,'' one can use exceptions
as an elegant way to end a loop involving an iterator, using the
built-in exception type {\bf StopIteration}.  For example: 

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
class fibnum20:
   def __init__(self):
      self.fn2 = 1  # "f_{n-2}"
      self.fn1 = 1  # "f_{n-1}"
   def next(self):  
      (self.fn1,self.fn2,oldfn2) = (self.fn1+self.fn2,self.fn1,self.fn2)
      if oldfn2 > 20: raise StopIteration
      return oldfn2
   def __iter__(self):
      return self
\end{Verbatim}

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from fib20 import *
>>> g = fibnum20()
>>> for i in g:
...    i
...
1
1
2
3
5
8
13
\end{Verbatim}

What happens is that iterating in the loop

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> for i in g:
\end{Verbatim}

catches the exception {\bf StopIteration}, which makes the looping
terminate, and our ``sequence'' is finite.

\subsubsection{``Circular'' Array Example}

Here's an example of using iterators to make a ``circular'' array.  In
Chapter \ref{chap:net}, we needed to continually cycle through a list
{\bf cs} of client sockets:\footnote{I am slightly modifying it here, by
assuming a constant number of clients.}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
while (1):
   # get next client, with effect of a circular queue
   clnt = cs.pop(0)
   ...
   cs.append(clnt)
   ...
\end{Verbatim}

Here's how to make an iterator out of it:\footnote{I've also made the
code more compact, independent of the change to an iterator.}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# circular queue

class cq:  # the argument q is a list
   def __init__(self,q):
      self.q = q
   def __iter__(self):
      return self
   def next(self):
      self.q = self.q[1:] + [self.q[0]]
      return self.q[-1]
\end{Verbatim}

Let's test it:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from cq import *
>>> x = cq([1,2,3])
>>> x.next()
1
>>> x.next()
2
>>> x.next()
3
>>> x.next()
1
>>> x.next()
2
\end{Verbatim}

With this, our {\bf while} loop in the network program above would look
like this:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
cit = cq(cs)
for clnt in cit:
   # code using clnt
   ...
\end{Verbatim}

The code would iterate indefinitely.

Of course, we had to do a bit of work to set this up.  But now that we
have, we can reuse this code in lots of different applications in the
future, and the nice, clear form such as that above,

\begin{Verbatim}[fontsize=\relsize{-2}]
for clnt in cs:
\end{Verbatim}

adds to ease of programming and readability of code.

\subsection{Overriding the next() Function:  File Subclass Example}

As mentioned, one can use a file as an iterator.  The {\bf file} class
does have member functions {\bf \_\_iter\_\_()} and {\bf next()}.  The
latter is what is called by {\bf readline()} and {\bf readlines()}, and
can be overriden.

Suppose we often deal with text files whose only elements are '0' and
'1', with the same number of elements per line.  We can form a class
{\bf file01} as a subclass of {\bf file}, and add some error checking:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
import sys

class file01(file):
   def __init__(self,name,mode,ni):
      file.__init__(self,name,mode)
      self.ni = ni  # number of items per line
   def next(self):
      line = file.next(self)
      items = line.split()
      if len(items) != self.ni:
         print 'wrong number of items'
         print line
         raise StopIteration
      for itm in items:
         if itm != '1' and itm != '0':
            print 'non-0/1 item:', itm
            raise StopIteration
      return line

def main():
   f = file01(sys.argv[1],'r',int(sys.argv[2]))
   for l in f: print l[:-1]

if __name__ == '__main__': main()
\end{Verbatim}

Here are some simple examples:

\begin{Verbatim}[fontsize=\relsize{-2}]
% cat u
1 0 1
0 1 1
% python file01.py u 3
1 0 1
0 1 1
% python file01.py u 2
wrong number of items
1 0 1

% cat v
1 1 b
1 0 1
% python file01.py v 3
non-0/1 item: b
\end{Verbatim}

One point to note here that you can open any file (not just of this new
special kind) by simply creating an instance of the {\bf file} class.
For example, this would open a file {\bf x} for reading and print its
lines:

\begin{Verbatim}[fontsize=\relsize{-2}]
f = file('x','r')
for l in f: print l
\end{Verbatim}

I've used that fact in {\bf main()} above.

Note also that in overriding {\bf file.next()}, we still need to call
it, in order to to read a line:

\begin{Verbatim}[fontsize=\relsize{-2}]
line = file.next(self)
\end{Verbatim}

\subsection{Iterator Functions}

\subsubsection{General Functions}

You can also make a real sequence out of an iterator's ``output'' by
using the {\bf list()} function, though you of course do have to make
sure the iterator produces finite output.  For example:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from fib20 import *
>>> g = fibnum20()
>>> g
<fib20.fibnum20 instance at 0xb7e6c50c>
>>> list(g)
[1, 1, 2, 3, 5, 8, 13]
\end{Verbatim}

The functions {\bf sum()}, {\bf max()} and {\bf min()} are built-ins for
iterators, e.g.

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from fib20 import *
>>> g = fibnum20()
>>> sum(g)
33
\end{Verbatim}

\subsubsection{Example:  Word Fetcher}
\label{itrwordfeth}

We have a text file, and wish to fetch words in the file one at a time.

\begin{lstlisting}[numbers=left]
class wordfetch:
   def __init__(self,fl):
      self.fl = fl
      # words remaining in current line
      self.words = []
   def __iter__(self): return self
   def next(self):
      if self.words == []:
         line = self.fl.readline()
         # check for end-of-file
         if line == '': raise StopIteration
         # remove end-of-line char
         line = line[:-1]  
         self.words = line.split()
      firstword = self.words[0]
      self.words = self.words[1:]
      return firstword
  
def main():
   f = wordfetch(open('x'))
   for word in f: print word
\end{lstlisting}

\subsubsection{The {\tt itertools} Module} 

Here you can really treat an infinite iterator like a ``sequence,''
using various tools in this module.

For instance, {\bf iterators.islice()} is handy:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> from itertools import *
>>> g = fibnum()
>>> list(islice(g,6))  # slice out the first 6 elements
[1, 1, 2, 3, 5, 8]
\end{Verbatim}

The general form of {\bf islice()} is

\begin{Verbatim}[fontsize=\relsize{-2}]
itertools.islice(iteratorname, [start], stop, [step])
\end{Verbatim}

Here we get elements {\it start}, {\it start} + {\bf step}, and so on,
but ending before element {\it stop}.

For instance:

\begin{Verbatim}[fontsize=\relsize{-2}]
>>> list(islice(g,3,9,2))
[3, 8, 21]
\end{Verbatim}

There are also analogs of the {\bf map()} and {\bf filter()} functions
which operate on real sequences.  The call 

\begin{Verbatim}[fontsize=\relsize{-2}]
itertools.imap(f, iter1, iter2, ...)
\end{Verbatim}

returns the stream {\bf f(iter1[0],iter2[0],...)}, which one can then
apply {\bf list()} to. 

The call

\begin{Verbatim}[fontsize=\relsize{-2}]
itertools.ifilter(boolean expression, iter)
\end{Verbatim}

applies the boolean test to each elment of the iterator stream.

\section{Generators}

\subsection{General Structures}

{\bf Generators} are entities which generate iterators!  Hence the
name.

There are two main goals:

\begin{itemize}

\item Generators provide a cleaner, clearer, more convenient ways to
create iterators.

\item Generators can be used to create {\bf coroutines}, which are quite
useful in certain applications, notably discrete-event simulation.

\end{itemize}

Roughly speaking, a generator is a function that we wish to call
repeatedly, but which is unlike an ordinary function in that successive
calls to a generator function don't start execution at the beginning of
the function.  Instead, the current call to a generator function will
resume execution right after the spot in the code at which the last call
exited, i.e. we ``pick up where we left off.''  

In other words, generators have some notion of ``state,'' where the
state consists of the line following the last one executed in the
previous call, and the values of local variables and arguments.

The way this occurs is as follows.  One calls the generator itself just
once.  That returns an iterator.  This is a real iterator, with {\bf
\_\_iter()\_\_} and {\bf next()} methods.  The latter is essentially the
function which implements our ``pick up where we left off'' goal.  We
can either call {\bf next()} directly, or use the iterator in a loop. 

Note that difference in approach:  

\begin{itemize}

\item In the case of iterators, a class is recognized by the Python
interpreter as an iterator by the presence of the {\bf \_\_iter()\_\_}
and {\bf next()} methods.  

\item By contrast, with a generator we don't even need to set up a
class.  We simply write a plain function, with its only distinguishing
feature for recognition by the Python interpreter being that we use {\bf
yield} instead of {\bf return}.

\end{itemize}

Note, though, that {\bf yield} and {\bf return} work quite differently
from each other.  When a {\bf yield} is executed, the Python interpreter
records the line number of that statement (there may be several {\bf
yield} lines within the same generator), and the values of the local
variables and arguments.  Then, the next time we call the {\bf .next()}
function of this same iterator that we generated from the generator
function, the function will resume execution at the line following the
{\bf yield}.  Depending on your application, the net effect may be very
different from the iterators we've seen so far, in a much more flexible
way.

Here are the key points:

\begin{itemize}

\item A {\bf yield} causes an exit from the function, but the next time
the function is called, we start ``where we left off,'' i.e.  at the
line following the {\bf yield} rather than at the beginning of the
function.

\item All the values of the local variables which existed at the time of
the {\bf yield} action are now still intact when we
resume.

\item There may be several {\bf yield} lines in the same generator.

\item We can also have {\bf return} statements, but execution of any
such statement will result in a {\bf StopIteration} exception being
raised if the {\bf next()} method is called again.

\item The {\bf yield} operation has one operand (or none), which is the
return value.  That one operand can be a tuple, though.  As usual, if
there is no ambiguity, you do not have to enclose the tuple in
parentheses.

\end{itemize}


Read the following example carefully, keeping all of the above points in
mind:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# yieldex.py example of yield, return in generator functions

def gy():
   x = 2
   y = 3
   yield x,y,x+y
   z = 12
   yield z/x
   print z/y
   return

def main():
   g = gy()
   print g.next()  # prints x,y,x+y
   print g.next()  # prints z/x
   print g.next()

if __name__ == '__main__':
   main()
\end{Verbatim}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% python yieldex.py
(2, 3, 5)
6
4
Traceback (most recent call last):
  File "yieldex.py", line 19, in ?
    main()
  File "yieldex.py", line 16, in main
    print g.next()
StopIteration
\end{Verbatim}

Note that execution of the actual code in the function {\bf gy()}, i.e.
the lines

\begin{Verbatim}[fontsize=\relsize{-2}]
x = 2
...
\end{Verbatim}

does not execute until the first {\bf g.next()} is executed.

Here is an odd observation:  The code for {\bf gy()} is fake!  It is not
executed {\it per se}.  Instead, the Python interpreter reads that code
and builds an iterator from it; we execute the iterator, not the
generator.

\subsection{Example:  Fibonacci Numbers}

As another simple illustration, let's look at the good ol' Fibonacci
numbers again:

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# fibg,py, generator example; Fibonacci numbers
# f_n = f_{n-1} + f_{n-2}

def fib():
   fn2 = 1  # "f_{n-2}"
   fn1 = 1  # "f_{n-1}"
   while True:
      (fn1,fn2,oldfn2) = (fn1+fn2,fn1,fn2)
      yield oldfn2
\end{Verbatim}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
>>> from fibg import *
>>> g = fib()
>>> g.next()
1
>>> g.next()
1
>>> g.next()
2
>>> g.next()
3
>>> g.next()
5
>>> g.next()
8
\end{Verbatim}

Note that the generator's trait of resuming execution ``where we left
off'' is quite necessary here.  We certainly don't want to execute

\begin{Verbatim}[fontsize=\relsize{-2}]
fn2 = 1
\end{Verbatim}

again, for instance.  Indeed, a key point is that the local variables
{\bf fn1} and {\bf fn2} retain their values between calls.  This is what
allowed us to get away with using just a function instead of a class.
This is simpler and cleaner than the class-based approach.  For
instance, in the code here we refer to {\bf fn1} instead of {\bf
self.fn1} as we did in our class-based version in Section \ref{fibitr}.
In more complicated functions, all these simplifications would add up to
a major improvement in readability. 

This property of retaining locals between calls is like that of locals
declared as {\bf static} in C.  Note, though, that in Python we might
set up several instances of a given generator, each instance maintaining
different values for the locals.  To do this in C, we need to have
arrays of the locals, indexed by the instance number.  It would be
easier in C++, by using instance variables in a class.

\subsection{Example:  Word Fetcher}
\label{genwordfetch}

The following is a producer/consumer example.  The producer, {\bf
getword()}, gets words from a text file, feeding them one at a time to
the consumer (in this case {\bf main()}).\footnote{I thank C. Osterwisch
for this much improved version of the code I had here originally.} In
the test here, the consumer is {\bf testgw.py}.

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# getword.py

# the function getword() reads from the text file fl, returning one word
# at a time; will not return a word until an entire line has been read

def getword(fl):
   for line in fl:
      for word in line.split():
         yield word
   return
\end{Verbatim}

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
# testgw.py, test of getword; counts words and computes average length
# of words

# usage:  python testgw.py [filename] 
# (stdin) is assumed if no file is specified)

from getword import *

def main():
   import sys
   # determine which file we'll evaluate
   try:
      f = open(sys.argv[1])
   except:
      f = sys.stdin
   # generate the iterator
   w = getword(f)
   wcount = 0
   wltot = 0
   for wrd in w:
      wcount += 1
      wltot += len(wrd)
   print "%d words, average length %f" % (wcount,wltot/float(wcount))

if __name__ == '__main__':
   main()
\end{Verbatim}

Notice how much simpler the generator version is here than the iterator
version back in Section \ref{itrwordfeth}.  A great example of the power
of generators!

\subsection{Mutiple Iterators from the Same Generator}

Note our phrasing earlier (emphasis added):

\begin{quote}

...the next time this generator function is called {\it with this same
iterator}, the function will resume execution at the line following the
{\bf yield}

\end{quote}

Suppose for instance that in the above word count example we have two
sorted text files, one word per line, and we wish to merge them into a
combined sorted file.  We could use our {\bf getword()} function above,
setting up two iterators, one for each file.  Note that we might reach
the end of one file before the other.  We would then continue with the
other file by itself.  To deal with this, we would have to test for the
{\bf StopIteration} exception to sense when we've come to the end of a
file.

% \subsection{Modularity/Reusability}
% 
% You may have noticed in the last example a similarity to Unix pipes.
% At the shell level, we can do a lot of everyday tasks by simply chaining
% together several shell commands into a pipe.  For instance, say I want
% to find out how many lines in the file {\bf g} contain the word 'Davis'.
% I could do this:
% 
% \begin{Verbatim}[fontsize=\relsize{-2}]
% % grep Davis x | wc -l
% \end{Verbatim}
% 
% The command {\bf wc} (``word count''), with its {\bf -l} option, counts
% lines.  So, {\bf grep} would find the file's lines that I want, and pass
% them on to {\bf wc} via the pipe, after which {\bf wc} would count them.
% 
% Similarly, the {\bf getword()} function above is producing output which
% then is used as input by our program {\bf testgw.py}.  We could chain
% several generators together in a ``pipe.''
% 
% This shows that one of the biggest advantages of using iterators, and
% especially generators, is modularity and reusability.  Once you write a
% few tools like this, you can keep making use of them in lots of
% applications that you write.  Of course, we could still do that with
% ordinary functions, but without the compact elegance and clarity that we
% get from iterators, e.g.
% 
% \begin{Verbatim}[fontsize=\relsize{-2}]
% for w in word:
% \end{Verbatim}
% 
% in the example above.

\subsection{The os.path.walk() Function} 

The function {\bf os.path.walk()} in Chapter \ref{chap:filedir}
is a generator.

\subsection{Don't Put yield in a Subfunction}

If you have a generator {\bf g()}, and it in turn calls a function {\bf
h()}, don't put a {\bf yield} statement in the latter, as the Python
interpreter won't know how to deal with it.

\subsection{Coroutines}

So far, our presentation on generators has concentrated on their ability
to create iterators.  Another usage for generators is the construction
of {\bf coroutines}.

This is a general computer science term, not restricted to Python, that
refers to subroutines that alternate in execution.  Subroutine A will
run for a while, then subroutine B will run for a while, then A again,
and so on.  Each time a subroutine runs, it will resume execution right where
it left off before.  That behavior of course is just like Python generators,
which is why one can use Python generators for that purpose.

Basically coroutines are threads, but of the nonpreemptive type.  In
other words, a coroutine will continue executing until it voluntarily
relinquishes the CPU.  (Of course, this doesn't count timesharing with
other unrelated programs.  We are only discussing flow of control among
the threads of one program.)  In ``ordinary'' threads, the timing of the
passing of control from one thread to another is to various degrees
random.

The major advantage of using nonpreemptive threads is that you do not
need locks, due to the fact that you are guaranteed that a thread runs
until it itself relinquishes control of the CPU.  This makes your code a
lot simpler and cleaner, and much easier to debug.  (The randomness
alone makes ordinary threads really tough to debug.)

The disadvantage of nonpreemptive threads is precisely its advantage:
Because only one thread runs at a time, one cannot use nonpreemptive
threads for parallel computation on a multiprocessor machine.

Some major applications of nonpreemptive threads are:

\begin{itemize}

\item servers

\item GUI programs

\item discrete-event simulation

\end{itemize}

In this section, we will see examples of coroutines, in SimPy, a
well-known Python discrete-event simulation library written by Klaus
Muller and Tony Vignaux.

% \subsubsection{My thrd Class}
% 
% Though most threading systems are preemptive, there are some prominent
% exceptions.  The GNU PTH library, for instance, is nonpreemptive and
% supports C/C++.  
% 
% Generators make it easy to develop a nonpreemptive threads package in
% Python.  The {\bf yield} construct is a natural way to relinquish the
% CPU, while ``saving one's place'' in order to resume later.  One writes
% the threads manager to give a thread a turn by simply calling {\bf
% i.next()}, where {\bf i} is the iterator for the thread.  That's what
% I've done here.
% 
% As an example of use of {\bf thrd}, we'll take the ``string build''
% example presented in Chapters \ref{chap:net} and \ref{chap:pythr}.
% Clients send characters one at a time to a server, which accumulates
% them in a string, which it echoes back to the clients.  
% 
% There are two major issues in the example.  First, we must deal with the
% fact that we have asynchronous I/O; the server doesn't know which client
% it will hear from next.  Second, we must make sure that the accumulated
% string is always updated atomically.
% 
% Here we will use nonblocking I/O to address the issue of asynchroneity.
% But atomicity will be no problem at all.  Again, since threads are never
% interrupted, we do not need locks.  Here is the code for the server:
% 
% \begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% # simple illustration of thrd module
% 
% # multiple clients connect to server; each client repeatedly sends a
% # letter k, which the server adds to a global string v and echos back
% # to the client; k = '' means the client is dropping out; when all
% # clients are gone, server prints final value of v
% 
% # this is the server
% 
% import socket  
% import sys
% from pth import *
% 
% class glbs:  # globals
%    v = ''  # the string we are building up from the clients
% 
% class serveclient(thrd):
%    def __init__(self,id,c):
%       thrd.__init__(self,id)  # like Threading class, we subclass thrd
%       self.c = c[0]  # socket for this client
%       self.c.send('c')  # confirm connection
%    def run(self):
%       while 1:
%          # receive letter or EOF signal from c
%          try:
%             k = self.c.recv(1)
%             if k == '': break
%             # concatenate v with k, but do NOT need a lock 
%             glbs.v += k
%             self.c.send(glbs.v)
%          except:
%             pass
%          # here comes the main difference; we use yield to relinquish
%          # our turn; yield allows one argument, in this case the tuple
%          # ('clnt loop','pause'); the first element, 'clnt loop' is for
%          # documentation and debugging purposes, but the second,
%          # 'pause', tells the threads manager what state we want this
%          # thread to be in, in this case Run
%          yield 'clnt loop', 'pause'
%       self.c.close()
% 
% def main():
%    lstn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
%    port = int(sys.argv[1])  # server port number
%    lstn.bind(('', port))
%    lstn.listen(5)
%    # initialize concatenated string, v
%    glbs.v = ''
%    # number of clients 
%    nclnt = 2
%    # accept calls from the clients
%    for i in range(nclnt):
%       (clnt,ap) = lstn.accept()
%       clnt.setblocking(0)  # set client socket to be nonblocking
%       # start thread for this client, with the first argument being a
%       # string ID I choose for this thread, and the second argument begin
%       # (a tuple consisting of) the socket
%       t = serveclient('client '+str(i),(clnt,))
%    # shut down the server socket, since it's not needed anymore 
%    lstn.close()
%    # start the threads; the call will block until all threads are done
%    thrd.tmgr()
%    print 'the final value of v is', glbs.v
% 
% if __name__ == '__main__':  main()
% \end{Verbatim}
% 
% Here is the client (which of course is not threaded):
% 
% \begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% # simple illustration of thrd module
% 
% # two clients connect to server; each client repeatedly sends a letter,
% # stored in the variable k, which the server appends to a global string
% # v, and reports v to the client; k = '' means the client is dropping
% # out; when all clients are gone, server prints the final string v
% 
% # this is the client; usage is
% 
% #    python clnt.py server_address port_number
% 
% import socket  
% import sys
% 
% s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
% host = sys.argv[1]  # server address
% port = int(sys.argv[2])  # server port
% s.connect((host, port))
% 
% confirm = s.recv(1)
% print confirm
% 
% while(1):
%    # get letter
%    k = raw_input('enter a letter:')
%    s.send(k)  # send k to server
%    # if stop signal, then leave loop
%    if k == '': break
%    v = s.recv(1024)  # receive v from server (up to 1024 bytes)
%    print v  
% 
% s.close() # close socket
% \end{Verbatim}
% 
% Note that as with the Python {\bf threading} module, the user must write
% a function named {\bf run} which will override the one built in to the
% {\bf thrd} class.  As before, that function describes the action of the
% thread.  The difference here, though, is that now this function is a
% generator, as you (and the Python interpreter) can tell from the
% presence of the {\bf yield} statement.
% 
% There is a separate thread for each client.  The thread for a given
% client will repeatedly execute the following cycle:
% 
% \begin{itemize}
%  
% \item Try to read a character from the client.
% 
% \item Process the character if there is one. 
% 
% \item Yield, allowing the thread for another client to run.
% 
% \end{itemize}
% 
% Again, since a thread will run until it hits a {\bf yield}, we don't
% need locks.  
% 
% Just as is the case with Python's ordinary threads, {\bf thrd} is good
% mainly for I/O-bound applications.  While one I/O action is being done
% in one thread, we can start another one in another thread.  A common
% example would be a Web server.  But those applications would be too huge
% to deal with in this tutorial, so we have that very simple toy
% example above.
% 
% Below is another toy example, even more contrived, but again presented
% here because it is simple, and because it illustrates the set/wait
% constructs not included in the last example.  There is really no way to
% describe the actions it takes, except to say that it is designed to
% exercise most of the possible {\bf thrd} operations.  Just look at the
% output shown below, and then see how the code works to produce that
% output.
% 
% \begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% a1 starts
% a1 x: 6
% a1 pauses
% a2 starts
% a2 x: 7
% a2 pauses
% b starts
% b pauses
% c1 starts
% c1 waits for a1-ev
% c2 starts
% c2 waits for a1-ev
% a1 z: 19
% a1 waits for b-ev
% a2 z: 21
% a2 waits for b-ev
% b.v: 8
% b sets b-ev
% a1 z: 19
% a1 sets a1-ev for all
% c1 quits
% events:
% b-ev: a2
% a1-ev:
% c2 quits
% events:
% b-ev: a2
% a1-ev:
% b sets b-ev but stays
% b quits
% a2 z: 21
% a2 quits
% a1 quits
% \end{Verbatim}
% 
% Here is the code:
% 
% \begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% from pth import *
% 
% class a(thrd):
%    def __init__(self,thrid):
%       thrd.__init__(self,thrid)
%       self.x = None
%       self.y = None
%       self.z = None
%       self.num = int(self.id[1])
%    def run(self):
%       print self.id, 'starts'
%       self.x = 5+self.num
%       self.y = 12+self.num
%       print self.id, 'x:', self.x
%       print self.id, 'pauses'
%       yield '1','pause'  # state in Run state
%       self.z = self.x + self.y
%       print self.id, 'z:', self.z
%       print self.id, 'waits for b-ev'
%       yield '2','wait','b-ev'  # enter Sleep state, waiting for the
%                                # event named 'b-ev'
%       print self.id, 'z:', self.z
%       if self.id == 'a1':
%          print 'a1 sets a1-ev for all'
%          yield '2a','set_all','a1-ev'  # wake up all threads waiting for 
%                                        # the event 'a1-ev'
%       print self.id, 'quits'
%       yield '3','quit'  # thread exits
% 
% class b(thrd):
%    def __init__(self,thrid):
%       thrd.__init__(self,thrid)
%       self.u = None
%       self.v = None
%    def run(self):
%       print 'b starts'
%       self.u = 5
%       print 'b pauses'
%       yield '11','pause'  # stay in Run state
%       self.v = 8
%       print 'b.v:', self.v
%       print 'b sets b-ev'
%       yield '12','set','b-ev'  # wake just one thread waiting for 'b-ev'
%       print 'b sets b-ev but stays'
%       yield 'uv','set_but_stay','b-ev'  # wake a thread but do NOT pause
%       print 'b quits' 
%       yield 'our last one','quit'  # exit
% 
% class c(thrd):
%    def __init__(self,thrid):
%       thrd.__init__(self,thrid)
%    def run(self):
%       print self.id, 'starts'
%       print self.id, 'waits for a1-ev'
%       yield 'cwait','wait','a1-ev'  # wate for 'a1-ev'
%       print self.id, 'quits'
%       thrd.prevs()
%       yield 'cquit','quit'  # exit
% 
% def main():
%     # the next few lines create a bunch of threads
%     ta1 = a('a1')
%     ta2 = a('a2')
%     tb = b('b')
%     tc1 = c('c1')
%     tc2 = c('c2')
%     thrd.tmgr()  # start the threads manager, so threads begin
% 
% if __name__ == '__main__': main()
% \end{Verbatim}
% 
% Now, how is all this done?  Below is the code for the {\bf thrd} library.
% 
% First read the comments at the top of the file, and then the {\bf
% \_\_init()\_\_} code.  Then glance at the code for the threads manager .
% The latter repeatedly does the following:
% 
% \begin{itemize}
% 
% \item get the first thread in the runnable list, {\bf thr}
% 
% \item have it run until it hits a {\bf yield}, by calling
% {\bf thr.itr.next()}
% 
% \item take whatever action (pause, wait, set, etc.) that the thread
% requested when it yielded
% 
% \end{itemize}
% 
% Then you should be able to follow the {\bf thrd} member functions fairly
% easily.
% 
% \begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
% # pth.py:  non-preemptive threads for Python; inspired by the GNU PTH
% # package for C/C++
% 
% # typical application will have one class for each type of thread; its
% # main() will set up the threads as instances of the classes, and lastly
% # will call thrd.tmgr()
% 
% # each thread type is a subclass of the class thrd; in that subclass,
% # the user must override thrd.run(), with the code consisting of the
% # actions the thread will take
% 
% # threads actions are triggered by the Python yield construct, in the
% # following format:
% 
% #    yield yieldID, action_string [, arguments]
% 
% # the yieldID is for application code debugging purposes
% 
% # possible actions:
% 
% #    yield yieldID, 'pause':  
% #       thread relinquishes this turn, rejoins runnable list at the end
% 
% #    yield yieldID, 'wait', eventID:  
% #       thread changes state to 'waiting', joins end of queue for
% #       the given event
% 
% #    yield yieldID, 'set', eventID:
% #       thread sets the given event, rejoins runnable list at the end;
% #       the thread, if any, at head of queue for this event is inserted 
% #       at the head of the runnable list
% 
% #    yield yieldID, 'set_but_stay', eventID:
% #       thread sets the given event, but remains at head of runnable list;
% #       thread, if any, at head of queue for the event is inserted in 
% #       runnable list following the head
% 
% #    yield yieldID, 'set_all', eventID:
% #       thread sets the given event, rejoins runnable list at the end;
% #       all threads in queue for the event are inserted at the head of
% #       the runnable list, in the same order they had in the queue 
% 
% #    yield yieldID, 'quit':
% #       thread exits
% 
% class thrd:
% 
%    runlst = []  # runnable thread list
%    evnts = {}  # a key is an event ID, a string; value is a list of
%                # threads waiting for that event
%    waitlst = []  # waiting thread list
%    didyield = None  # thread that last performed a yield op; for
%                     # application code debugging purposes
% 
%    def __init__(self,id):
%       self.id = id  # user-supplied string
%       self.state = 'runnable'  # the other possible state is 'waiting'
%       self.yieldact = ''  # action at last yield; for application code
%                           # debugging purposes
%       self.waitevnt = ''  # what event this thread is waiting for, if any;
%                           # for application code debugging purposes
%       self.itr = self.run()  # this thread's iterator
%       thrd.runlst.append(self)
% 
%    def run(self):  # stub, must override
%       pass
% 
%    # triggered by:  yield yieldID, 'pause'
%    def do_pause(self,yv):
%       del thrd.runlst[0]
%       thrd.runlst.append(self) 
% 
%    # triggered by:  yield yieldID, 'wait', eventID
%    def do_wait(self,yv):
%       del thrd.runlst[0]
%       self.state = 'waiting'
%       self.waitevnt = yv[2] 
%       # check to see if this is a new event
%       if yv[2] not in thrd.evnts.keys():
%          thrd.evnts[yv[2]] = [self]
%       else:
%          thrd.evnts[yv[2]].append(self) 
%       thrd.waitlst.append(self) 
% 
%    # reactivate first thread waiting for this event, and place it at
%    # position pos of runlst
%    def react(ev,pos):
%       thr = thrd.evnts[ev].pop(0)
%       thr.state = 'runnable'
%       thr.waitevnt = ''
%       thrd.waitlst.remove(thr)
%       thrd.runlst.insert(pos,thr)
%    react = staticmethod(react)
% 
%    # triggered by:  yield yieldID, 'set', eventID
%    def do_set(thr,yv):
%       del thrd.runlst[0]
%       thrd.runlst.append(thr) 
%       thrd.react(yv[2],0)
%    do_set = staticmethod(do_set)
% 
%    # triggered by:  yield yieldID, 'set_but_stay'
%    def do_set_but_stay(thr,yv):
%       thrd.react(yv[2],1)
%    do_set_but_stay = staticmethod(do_set_but_stay)
% 
%    # triggered by:  yield yieldID, 'set_all', eventID
%    def do_set_all(self,yv):
%       del thrd.runlst[0]
%       ev = yv[2]
%       for i in range(len(thrd.evnts[ev])):
%          thrd.react(ev,i)
%       thrd.runlst.append(self) 
% 
%    # triggered by:  yield yieldID, 'quit'
%    def do_quit(self,yv):
%       del thrd.runlst[0]
% 
%    # for application code debugging
%    # prints info about a thread
%    def prthr(self):
%       print 'ID: %s, state: %s, ev: %s, yldact: %s' % \
%          (self.id, self.state, self.waitevnt, self.yieldact)
% 
%    # for application code debugging
%    # print info on all threads
%    def prthrs():
%       print 'runlst:'
%       for t in thrd.runlst:
%          t.prthr()
%       print 'waiting list:'
%       for t in thrd.waitlst:
%          thrd.prthr(t)
%    prthrs = staticmethod(prthrs)
% 
%    # for application code debugging
%    # printf info on all events
%    def prevs():
%       print 'events:'
%       for eid in thrd.evnts.keys():
%          print '%s:' % eid,
%          for thr in thrd.evnts[eid]:
%             print thr.id,
%          print 
%    prevs = staticmethod(prevs)
% 
%    # threads manager
%    def tmgr():
%       # while still have runnable threads, cycle repeatedly through them
%       while (thrd.runlst):
%          # get next thread
%          thr = thrd.runlst[0]
%          # call it
%          yieldvalue = thr.itr.next()  
%          # the above call to next() runs the thread until a yield, with
%          # the latter returning yieldvalue
%          thr.yieldID = yieldvalue[0]
%          thrd.didyield = thr
%          # call the function requested in the yield
%          yv1 = yieldvalue[1]  # requested action
%          thr.yieldact = yv1
%          actftn = eval('thrd.do_'+yv1)
%          actftn(thr,yieldvalue)
%    tmgr = staticmethod(tmgr)
% \end{Verbatim}

\subsubsection{The SimPy Discrete Event Simulation Library}

In discrete event simulation (DES), we are modeling discontinuous
changes in the system state.  We may be simulating a queuing system, for
example, and since the number of jobs in the queue is an integer, the
number will be incremented by an integer value, typically 1 or
-1.\footnote{{\bf Batch queues} may take several jobs at a time, but the
increment is still integer-valued.}  By contrast, if we are modeling a
weather system, variables such as temperature change continuously.

The goal of DES is typically to ask ``What if?'' types of questions.  An
HMO might have nurses staffing advice phone lines, so one might ask, how
many nurses do we need in order to keep the mean waiting time of
patients below some desired value?

SimPy is a widely used open-source Python library for DES.  Following is
an example of its use.  The application is an analysis of a pair of
machines that break down at random times, and need random time for
repair.  See the comments at the top of the file for details, including
the quantities of interest to be computed.

\begin{Verbatim}[fontsize=\relsize{-2},numbers=left]
#!/usr/bin/env python

# MachRep.py

# SimPy example:  Two machines, but sometimes break down.  Up time is
# exponentially distributed with mean 1.0, and repair time is
# exponentially distributed with mean 0.5.  In this example, there is
# only one repairperson, so the two machines cannot be repaired
# simultaneously if they are down at the same time.

# In addition to finding the long-run proportion of up time, let's also
# find the long-run proportion of the time that a given machine does not
# have immediate access to the repairperson when the machine breaks
# down.  Output values should be about 0.6 and 0.67.

from SimPy.Simulation import *
from random import Random,expovariate,uniform

class G:  # globals
   Rnd = Random(12345)
   # create the repairperson 
   RepairPerson = Resource(1)

class MachineClass(Process):
   TotalUpTime = 0.0  # total up time for all machines
   NRep = 0  # number of times the machines have broken down
   NImmedRep = 0  # number of breakdowns in which the machine 
                  # started repair service right away
   UpRate = 1/1.0  # breakdown rate
   RepairRate = 1/0.5  # repair rate
   # the following two variables are not actually used, but are useful
   # for debugging purposes
   NextID = 0  # next available ID number for MachineClass objects
   NUp = 0  # number of machines currently up
   def __init__(self):
      Process.__init__(self)  
      self.StartUpTime = 0.0  # time the current up period started
      self.ID = MachineClass.NextID   # ID for this MachineClass object
      MachineClass.NextID += 1
      MachineClass.NUp += 1  # machines start in the up mode
   def Run(self):
      while 1:
         self.StartUpTime = now()  
         # simulate up time for this machine
         yield hold,self,G.Rnd.expovariate(MachineClass.UpRate)
         # a breakdown has occurred on this machine
         MachineClass.TotalUpTime += now() - self.StartUpTime
         # update number of breakdowns
         MachineClass.NRep += 1
         # check whether we get repair service immediately; how many
         # repairpersons (1 or 0 here) are available?
         if G.RepairPerson.n == 1:
            MachineClass.NImmedRep += 1
         # need to request, and possibly queue for, the repairperson;
         # we'll basically come back right after if the repairperson is
         # free
         yield request,self,G.RepairPerson
         # OK, we've obtained access to the repairperson; now
         # hold for repair time
         yield hold,self,G.Rnd.expovariate(MachineClass.RepairRate)
         # release the repairperson
         yield release,self,G.RepairPerson

def main():
   initialize()  
   # set up the two machine processes
   for I in range(2):
      M = MachineClass()
      activate(M,M.Run())
   MaxSimtime = 10000.0
   simulate(until=MaxSimtime)
   print 'proportion of up time:', MachineClass.TotalUpTime/(2*MaxSimtime)
   print 'proportion of times repair was immediate:', \
      float(MachineClass.NImmedRep)/MachineClass.NRep

if __name__ == '__main__':  main()
\end{Verbatim}

Again, make sure to read the comments in the first few lines of the code
to see what kind of system this program is modeling before going
further.

Now, let's see the details.

SimPy's thread class is {\bf Process}.  The application programmer
writes one or more subclasses of this one to serve as SimPy thread
classes.  Similar to the case for the {\bf threading} class, the
subclasses of {\bf Process} must include a method {\bf Run()}, which
describes the actions of the SimPy thread.  

The SimPy method {\bf activate()} is used to add a SimPy thread to the
run list.  Remember, though, that the {\bf Run()} methods are
generators.  So, activation consists of calling {\bf Run()}, producing
an iterator.  So for instance, the line from the above code,

\begin{lstlisting}
activate(M,M.Run())
\end{lstlisting}

has a {\it call} to {\bf M.Run} as an argument, rather than the function
itself being the argument.  In other words, the argument is the
iterator.  More on this below.

The main new ingredient here is the notion of simulated time.  The
current simulated time is stored in the variable {\bf Simulation.\_t}.
Each time an event is created, via execution of a statement like

\begin{Verbatim}[fontsize=\relsize{-2}]
yield hold, self, holdtime
\end{Verbatim}

Recall that {\bf yield} can have one argument, which in this case is the
tuple {\bf (hold, self, holdtime)}.  (Remember, parentheses are optional
in tuples.)  

The value {\bf hold} is a constant within SimPy, and it signifies,
``hold for the given amount of simulated time before continuing.  SimPy
schedules the event to occur {\bf holdtime} time units from now, i.e. at
time {\bf Simulation\_t+holdtime}.  What I mean by ``schedule'' here is
that SimPy maintains an internal data structure which stores all future
events, ordered by their occurrence times.  Let's call this the
scheduled events structure, SES.  Note that the elements in SES are
SimPy threads, i.e. instances of the class {\bf Process}.  A new event
will be inserted into the SES at the proper place in terms of time
ordering.

The main loop in SimPy repeatedly cycles through the following:

\begin{itemize}

\item Remove the earliest event, say {\bf v}, from SES.  

\item If the occurrence time of {\bf v} is past the simulation limit,
exit the loop.  Otherwise, advance the simulated time clock {\bf
Simulation.\_t} to the occurrence time of {\bf v}.

\item Call the {\bf .next()} method of iterator for {\bf v}, i.e. the
iterator for the {\bf Run()} generator of that thread, thus causing the
code in {\bf Run()} to resume at the point following its last executed
{\bf yield}.  

\item Act on the result of the next {\bf yield} that {\bf Run()} hits
(could be the same one, in a loop), e.g. handle a {\bf hold} command.
(Note that {\bf hold} is simply a constant in the SimPy internals, as
are the other SimPy actions such as {\bf request} below.)

\end{itemize}

Note that this is similar to what an ordinary threads manager does, but
differs due to the time element.  In ordinary threads programming, there
is no predicting as to which thread will run next.  Here, we know which
one it will be.\footnote{This statement is true as long as there are no
tied event times, which in most applications do not occur.  In most
applications, the main hold times are exponentially distributed, or have
some other continuous distribution.  Such distributions imply that the
probability of a tie is 0, and though that is not strictly true given
the finite word size of a machine, in practice one usually doesn't worry
about ties.}


In simulation programming, we often need to have one entity wait for
some event to occur.  In our example here, if one machine goes down
while the other is being repaired, the newly-broken machine will need to
wait for the repairperson to become available.  Clearly this is like the
condition variables construct in most threads packages. 

Specifically, SimPy includes a {\bf Resource} class.  In our case here,
the resource is the repairperson.  When a line like

\begin{Verbatim}[fontsize=\relsize{-2}]
yield request,self,G.RepairPerson
\end{Verbatim}

is executed, SimPy will look at the internal data structure in which
SimPy stores the queue for the repairperson.  If it is empty, the thread
that made the request will acquire access to the repairperson, and
control will return to the statement following {\bf yield request}.  If
there are threads in the queue (here, there would be at most one), then
the thread which made the request will be added to the queue.  Later,
when a statement like

\begin{Verbatim}[fontsize=\relsize{-2}]
yield release,self,G.RepairPerson
\end{Verbatim}

is executed by the thread currently accessing the repairperson, SimPy
will check its queue, and if the queue is nonempty, SimPy will remove
the first thread from the queue, and have it resume execution where it
left off.\footnote{This will not happen immediately.  The thread that
triggered the release of the resource will be allowed to resume
execution right after the {\bf yield release} statement.  But SimPy will
place an artificial event in the SES, with event time equal to the
current time, i.e. the time at which the release occurred.  So, as soon
as the current thread finishes, the awakened thread will get a chance to
run again, most importantly, at the same simulated time as before.}

Since the simulated time variable {\bf Simulation.\_t} is in a separate
module, we cannot access it directly.  Thus SimPy includes a ``getter''
function, {\bf now()}, which returns the value of {\bf Simulation.\_t}.

Most discrete event simulation applications are stochastic in nature,
such as we see here with the random up and repair times for the
machines.  Thus most SimPy programs import the Python {\bf random}
module, as in this example. 

For more information on SimPy, see the files {\bf DESimIntro.pdf}, {\bf
AdvancedSimPy.pdf} and {\bf SimPyInternals.pdf} in
\url{http://heather.cs.ucdavis.edu/~matloff/156/PLN}.

