[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