[Twisted-Python] Re: Twisted-Python] how to create state machines?
Andrew Francis
andrewfr_ice at yahoo.com
Thu Mar 26 22:48:48 MDT 2009
Hi Doug:
>Message: 1
>Date: Thu, 26 Mar 2009 14:26:17 -0400
>From: "Doug Farrell" <dfarrell at mypublisher.com>
>Subject: [Twisted-Python] how to create state machines?
>To: <twisted-python at twistedmatrix.com>
>Message-ID:
<318F79422ADC5041A93343721F84474D01A8BB43 at exchange.mypublisher.local>
>Content-Type: text/plain; charset="us-ascii"
>This state machine initializes a system, issues an asynchronous command
>that takes time to complete (say a motor move command) and then waits
>for that command to be done before exiting. In the context of a
>framework that is calling this state machine, the WAITCMD1 is executed
>repeatedly (polling) while the asynchronous command completes. A system
>can be constructed with lots of little state machines like this and be
>made to look like it is doing many things at once even though the
>execution of the program is single threaded.
>I understand (pretty much) the Twisted framework is like this and
>implmenting event handlers like connectionMade(), etc., is a state
>machine, but I'm wondering how to implement what I've outlined above in
>one of Twisted's state event handlers, or inside something like
>callLater(). For example, let's say I want to use Twisted to run a long
>running daemon process that has an XMLRPC interface. That XMLRPC
>interface is an interface to a state machine inside Twisted that allows
>the caller to change state, or start new state machines, or get the
>status of a running state machine. In that case I'm thinking I want a
>state machine the runs continuously in the Twisted loop, structured like
>the example above; co-operatively yielding back to Twisted, but running
>non-stop. Something like callLater(1, stateMachine), but non-stop,
>without even the 1 second call loop.
If I understand your correctly, I don't think you need to implement a state machine to simulate concurrency with Twisted - Twisted does a lot of that for you. You can think of a Twisted application as a state machine - the callback being the state and the completion of the operation and the calling of the callback is the transition. These callbacks at runtime act like a thread of execution.
def Initialize(...):
# do something
deferred = someFunctionThatReturnsADeferred()
deferred.addCallback(State2)
def State2(...):
# do something
deferred = someFunctionThatReturnsADeferred()
deferred.addCallback(State3)
def State3(someData):
# do something
if someData == 'State4':
deferred = someFunctionThatReturnsADeferred()
func = State4
elif someData == 'State5':
deferred = someOtherFunctionThatReturnsADeferred()
func = State5
...
deferred.addCallback(func)
if __name__ = "__main__":
initialize()
reactor.run()
As for the Twisted loop. Well, you don't really see the Twisted loop since that is hidden in the reactor. Also you should distinguish between writing a new protocol and using an existing one.
In the case of XMLRPC, creating the server isn't the problem.
http://twistedmatrix.com/projects/web/documentation/howto/xmlrpc.html
Once a XMLRPC server is created, Twisted will take responsibility for creating new instances (or threads if you want to see it that way). If you still need a state machine, then the only hiccup I can see is sharing state machine (if you really need one) between XMLRPC method invocations.
Cheers,
Andrew
More information about the Twisted-Python
mailing list