[Qt-interest] Initializing application modules in sequence
Sean Harmer
sean.harmer at maps-technology.com
Mon Apr 25 16:27:39 CEST 2011
Hi,
On 25/04/2011 14:41, Mandeep Sandhu wrote:
>> It sounds as if QStateMachine would be a good candidate here. We do
>> something similar with hardware devices (usb or Ethernet based).
>
> That was my initial thought too... :)
Great minds and all that :D
> Won't async/non-blocking init's require some sort of a parallel state
> group? Take the following init steps eg:
>
> 1 (B) -> 2 (B) -> 3 (NB) -> 4 (NB)
> +-> 5 (B)
>
> B=blocking
> NB=non-blocking
>
> In such case I could add states/transitions depicting the steps as :
>
> 1 -> 2 -> 5 and 3 and 4 should be performed in parallel after 2 is done.
>
> However, for steps 3 and 4, I'd like to start them the moment step 2
> is done. 1 way is to add a sub-state to state 5 and a parallel state
> group with 2 parallel states representing steps 3 and 4. So both of
> them (3& 4) will be started when we enter state 5
Yes something along those lines would do nicely. Another similar pattern
I have used in a SM controlled system with many subsystems is to have
each subsystem controlled by it's own state hierarchy. These subsystem
states all exist in parallel at the top-level along with a controller
state. Something like this:
Controller State | Subsys1 State | Subsys2 state | ... | SubsysN State
The subsystem states perform actions (ie transition to sub-states) in
response to events posted by sub-states of the controller state. The
controller state itself transitions between substates using guarded
transitions in response to events posted by the subsystem sub-states.
This SM pattern might be better here than what I originally suggested.
As an example, let's consider your case outlined above. The controller
state would upon start of the SM transition into the "Init Subsys1
State" which would post and event that only SubSystem1 would transition on.
When Subsys1 has finished it's initialisation (blocking) it posts
another event which causes the controller to transition to "Init Subsys2
State" which does something similar to the above.
Then when the controller sees the event saying that Subsys2 has been
initialised it posts another custom event that causes subsystems 3 and 4
to transition to their sub-states that starts their initialisation
routines.
As each of 3 and 4 finishes they post another custom event that tells
the controller they have finished. However, for this transition the
controller has a guarded transition that checks for both 3 and 4 to be
in their "Initialised" substates. Only then does it transition to the
"Init Subsys5 State" and does similar to steps 1 and 2.
> I found using SM for such init routines a little rigid. It also
> requires one to change the SM each time a new/different sequence of
> init's is required.
I found that with a sensible set of custom states, events and
transitions that the SM framework made my life easier. If you wish to
change something it simply becomes a job of re-plumbing that isolated
section of the SM. For example in the above you would only have to
modify the transitions in the controller state. Each subsystem's states
are independent.
>
> Another thought that I want to bounce off others:
>
> * Have a controller class...say InitManager (initmgr for short).
> * All modules that need initialization implement an interface so that
> the initmgr has a uniform way of talking to, with all modules.
> * Modules register themselves with this class either in blocking or
> non-blocking mode.
> * For blocking mode, they are invoked in the order in which they were
> registered, each time initmgr waits for a signal from the module which
> indicates init completion.
> * For non-blocking mode too they are invoked in the order in which
> they were registered, but the initmgr does not wait for init
> completion.
> * Final completion is assumed when all (B& NB) modules have signaled
> successful completion.
>
> To keep it simple I've removed the requirement of having a
> 'dependency' though. In case a module 'C' requires module 'A' to be
> done before, then 'A' must be made blocking and 'C' should be
> registered _after_ 'A'. So with this limitation, all modules which do
> not have any dependencies can be marked as non-blocking and others as
> blocking.
This seems like a hack to achieve what the SM provides naturally.
> With this approach I can also give out some sort of 'x percentage
> completed' signal to a user who might want to show the init progress.
You can also do this easily with the SM approach. Just emit a progress
signal at suitable points in the controller states/transitions.
>> Hope that helps but feel free to come back with more questions if
>> anything is not clear from those ramblings ;-)
>
> Your 'ramblings' are very valuable (my understanding of QSM was made
> easy by you and others on this list). Thanks again for your input!
No problem. Glad to be of any little help. I really think that the
QtStateMachine framework is one of the most under-valued parts of Qt. It
makes certain types of problems very trivial. It just requires a little
shift in mindset but the learning curve is well worth the reward -
especially when you come to maintain something 12 months from now. ;-)
Cheers,
Sean
More information about the Qt-interest-old
mailing list