[py-svn] r11507 - py/dist/py/documentation

arigo at codespeak.net arigo at codespeak.net
Wed Apr 27 12:06:46 CEST 2005


Author: arigo
Date: Wed Apr 27 12:06:46 2005
New Revision: 11507

Modified:
   py/dist/py/documentation/greenlet.txt
Log:
Added the greenlet example from my ACCU lightning talk.


Modified: py/dist/py/documentation/greenlet.txt
==============================================================================
--- py/dist/py/documentation/greenlet.txt	(original)
+++ py/dist/py/documentation/greenlet.txt	Wed Apr 27 12:06:46 2005
@@ -30,6 +30,75 @@
 .. _`Stackless`: http://www.stackless.com
 .. _`test_generator.py`: http://codespeak.net/svn/user/arigo/greenlet/test_generator.py
 
+Example
+-------
+
+Let's consider a system controlled by a terminal-like console, where the user
+types commands.  Assume that the input comes character by character.  In such
+a system, there will typically be a loop like the following one::
+
+    def process_commands(*args):
+        while True:
+            line = ''
+            while not line.endswith('\n'):
+                line += read_next_char()
+            if line == 'quit\n':
+                print "are you sure?"
+                if read_next_char() != 'y':
+                    continue    # ignore the command
+            process_command(line)
+
+Now assume that you want to plug this program into a GUI.  Most GUI toolkits
+are event-based.  They will invoke a call-back for each character the user
+presses.  [Replace "GUI" with "XML expat parser" if that rings more bells to
+you ``:-)``]  In this setting, it is difficult to implement the
+read_next_char() function needed by the code above.  We have two incompatible
+functions::
+
+    def event_keydown(key):
+        ?? 
+
+    def read_next_char():
+        ?? should wait for the next event_keydown() call
+
+You might consider doing that with threads.  Greenlets are an alternate
+solution that don't have the related locking and shutdown problems.  You
+start the process_commands() function in its own, separate greenlet, and
+then you exchange the keypresses with it as follows::
+
+    def event_keydown(key):
+             # jump into g_processor, sending it the key
+        g_processor.switch(key)
+
+    def read_next_char():
+            # g_self is g_processor in this simple example
+        g_self = greenlet.getcurrent()
+            # jump to the parent (main) greenlet, waiting for the next key
+        next_char = g_self.parent.switch()
+        return next_char
+
+    g_processor = greenlet(process_commands)
+    g_processor.switch(*args)   # input arguments to process_commands()
+
+    gui.mainloop()
+
+In this example, the execution flow is: when read_next_char() is called, it
+is part of the g_processor greenlet, so when it switches to its parent
+greenlet, it resumes execution in the top-level main loop (the GUI).  When
+the GUI calls event_keydown(), it switches to g_processor, which means that
+the execution jumps back wherever it was suspended in that greenlet -- in
+this case, to the switch() instruction in read_next_char() -- and the ``key``
+argument in event_keydown() is passed as the return value of the switch() in
+read_next_char().
+
+Note that read_next_char() will be suspended and resumed with its call stack
+preserved, so that it will itself return to different positions in
+process_commands() depending on where it was originally called from.  This
+allows the logic of the program to be kept in a nice control-flow way; we
+don't have to completely rewrite process_commands() to turn it into a state
+machine.
+
+
 Usage
 =====
 



More information about the pytest-commit mailing list