Using python coroutines to implement easy of use state machines
Michael 'Mickey' Lauer
mickey at vanille-media.de
Tue Jun 3 13:41:26 CEST 2008
On Wednesday 28 May 2008 08:42:22 Guillaume Chereau wrote:
> On Tue, 2008-05-27 at 14:41 +0800, Guillaume Chereau wrote:
> > Aah, I just finished doing a simple "proof of concept" library to show
> > how it could work (server side). I am quite happy with it because it
> > allows generators OR callbacks syntax (in fact the library just provides
> > a wrapper to a callback mechanism), so it is very easy to use with the
> > gobject callback functions.
Awesome, thanks a lot. I think this will be very handy in a lot of places,
especially client side. I solved it a bit differently in the ophoned server
though, because a) we don't need traceback exception handling here (since
exceptions come in other form), and I adore the simplicity and elegance of
the <result> = yield <request> form.
For reference, this is what I came up with:
#=========================================================================#
class AbstractYieldSupport( object ):
#=========================================================================#
"""
This class adds support for simplifying control flow
by using Python generators to implement coroutines.
By inheriting from this class, you can use the following syntax:
def trigger( self ):
for iteration in ( 1,2,3,4 ):
request, response, error = yield( "+CFUN=1" )
if error is None:
self._ok( response )
else:
self.errorFromChannel( request, error )
"""
def __init__( self, *args, **kwargs ):
self.generator = self.trigger()
if self.generator is not None:
toEnqueue = self.generator.next()
self._commchannel.enqueue( toEnqueue, self.genResponseFromChannel,
self.genErrorFromChannel )
def trigger( self ):
assert False, "pure virtual method called"
@logged
def genResponseFromChannel( self, request, response ):
try:
toEnqueue = self.generator.send( ( request, response, None ) )
except StopIteration:
pass
else:
self._commchannel.enqueue( toEnqueue, self.genResponseFromChannel,
self.genErrorFromChannel )
@logged
def genErrorFromChannel( self, request, error ):
try:
toEnqueue = self.generator.send( ( request, None, error ) )
except StopIteration:
pass
else:
self._commchannel.enqueue( toEnqueue, self.genResponseFromChannel,
self.genErrorFromChannel )
:M:
--
Dr. Michael 'Mickey' Lauer | IT-Freelancer | http://www.vanille-media.de
More information about the smartphones-standards
mailing list