Ugh, seems this didn't go to the list... forwarding it there. ---------- Forwarded message ---------- From: Aleric Inglewood <aleric.inglew...@gmail.com> Date: Mon, Feb 15, 2010 at 12:22 AM Subject: Re: [opensource-dev] State machine class To: Melinda Green <meli...@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 <meli...@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