[opensource-dev] Fwd: State machine class

Morgaine morgaine.dinova at googlemail.com
Mon Feb 15 08:15:46 PST 2010


That's a very hard-wired approach, and it achieves nothing that cannot be
done much more simply and safely in user scripting processes.  When things
go wrong with scripts, you don't want them going wrong in the core viewer.
A bad script running as an external process can simply be terminated ---
that's a much cleaner and safer approach.

What's more, your method handles only the simplest of state scripting
requirements directly, because the state switching conditions will
necessarily be of limited complexity and predefined in C++ code --- the
scripts themselves would have to set up more complex conditional triggers on
the fly by orchestrating multiple sub-states.

That is totally unnecessary, and a weak approach.  If you let each script
maintain its own state in the normal manner for sequential programs, and
merely send it the events to which it has subscribed, then the script can
implement arbitrary conditional state switching very simply using
conventional programming.


Morgaine.




================================

On Sun, Feb 14, 2010 at 11:27 PM, Aleric Inglewood <
aleric.inglewood at gmail.com> wrote:

> Ugh, seems this didn't go to the list... forwarding it there.
>
> ---------- Forwarded message ----------
> From: Aleric Inglewood <aleric.inglewood at gmail.com>
> Date: Mon, Feb 15, 2010 at 12:22 AM
> Subject: Re: [opensource-dev] State machine class
> To: Melinda Green <melinda at superliminal.com>
>
>
> I am already using it :p.
> This proposal is the direct result of practical experience, showing me that
> this is needed.
>
> But before I start to write example code that uses it, allow me to stay
> abstract.
>
> Didn't get much (other) reactions, so I thought I'd add some more details.
>
> The idea is to have objects that go through a series of (usually)
> sequential states:
>
> CONSTRUCTOR
>      |
>      v
>    INIT
>      |
>      v
> custom states --------.
>      .                |
>      .                |
>      .                v
> custom states ----->ABORT
>      |                |
>      |<---------------'
>      v
>    DONE
>
>
> 'CONSTRUCTOR' would be an uninitialized state and never really executed
> (the 'state' variable during construction of the object). Obviously it
> would
> be in balance with it's destructor.
>
> 'INIT' would be the first state of the object when 'run'.
> If the whole finishes successfully, we end up in the state 'DONE',
> which cleanup in balance with INIT, and anything that is expected
> to be left over from going to the states successfully.
>
> The ABORT state is a state that will cleanup anything that might
> be left-over from an abort.
>
> The main thread ''runs' the object from it's 'Idle' state by calling
> gIdleCallbacks.addFunction(...) for this object.
>
> The main loop of such a StateMachine object would then look
> like something like:
>
> switch(mState)
> {
>   case INIT:
>     init();
>     set_state(WAIT_FOR_FOO);
>   case WAIT_FOR_FOO;
>     if (!foo())
>       idle();
>     set_state(DO_MORE);
>   case DO_MORE:
>     do_it();
>     set_state(WAIT_FOR_BAR);
>   case WAIT_FOR_BAR:
>     if (!bar())
>       idle();
>     set_state(DONE);
>   case DONE:
>     cleanup();
> }
>
> As you see, this gives a compact and clear code where the flow is intuitive
> (top down), but asynchronus and "blocking", without actually blocking the
> main loop.
>
> One of the major advantages is these objects are reusable; for example, one
> could write an object that checks if some inventory folder exists, if not
> creates it, and then (or when it already exists) waits till it's contents
> are available. Lets call this object SyncFolder(std::string const& name).
>
> Then another StateMachine object can use it (for example) as follows:
>
> class MyStateMachine : public LLStateMachine {
>   SyncFolder mSyncFolder;
> ...
>   virtual void init();
>   virtual void abort();
>   virtual void done();
> };
>
> void MyStateMachine::init()
> {
>   mSyncFolder.set_name(folder_name);
> }
>
> bool MyStateMachine::mainloop()
> {
>   // INIT, DONE and ABORT are handled by the base class.
>   switch(mState)
>   {
>     case WAIT_FOR_FOO:
>       if (!foo())
>         idle();
>       set_state(SYNC_FOLDER);
>     case SYNC_FOLDER:
>       if (!mSyncFolder())   // Returns true when DONE
>         break;
>     case REZ_ITEM_FROM_FOLDER:
>       do_rez();
>   }
> }
>
>
> One could create a large number of such objects that do simple tasks, and
> then use those to build
> objects that do more complex tasks.
>
>
> On Thu, Feb 11, 2010 at 6:56 PM, Melinda Green <melinda at superliminal.com>wrote:
>
>> Sounds like a solution in search of a problem. I suggest that in order to
>> get it incorporated as core, that you create at least one compelling
>> solution built on it that people want enough to incorporate the whole thing.
>> If you can't come up with one then it probably doesn't belong there because
>> without a compelling example, nobody is going to realize it's there or to
>> trust it or know how to use it.
>>
>> Just my L$5,
>> -Melinda
>>
>
>
> _______________________________________________
> Policies and (un)subscribe information available here:
> http://wiki.secondlife.com/wiki/OpenSource-Dev
> Please read the policies before posting to keep unmoderated posting
> privileges
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.secondlife.com/pipermail/opensource-dev/attachments/20100215/fabb5908/attachment.htm 


More information about the opensource-dev mailing list