Hi,
FYI: my library that uses the boost.msm-based state machine mechanism shall be released as shared library. It is used to realize Remote Procedure Calls. So my library consists of one Master state machine (which consists of 5 submachines and together 21 states) and one Slave state machine (which consists of 4 submachines and 19 states). The user application linking against my library has the possibility to choose if the slave state machine or the master state machine part shall be used. Now the problem could be, that I use a boost::variant type to store the 44 different application event types. This variant type I pass to the process_event method of each state machine (master and slave) although the slave state machine doesn't support the same event types like the master and vice-versa. This produces unnecessary template invocations and memory allocation.
Yes, every process_event with a different event type costs template instantiations, and process_event is the most expensive part.
So the solution could be, to split my single shared library into two shared libraries: one for the master and one for the slave logic and each of it has a reduced boost::variant type( just with the event types of the concrete state machine).
Sounds logical. Though I don't get it with the variant. Are you doing type switching with boost::get? You could also do 1 library with 2 different classes, each implemented with one different fsm. Maybe some states or actions can be reused, though it doesn't improve your compile-time. In any case, 2 TUs are nicer to the compiler than 1 big one, yes. I will also take the chance to advertise type_erasure (see a previous post on this list) as a good replacement of boost::variant.
Or I keep the solution with the single shared library and I split the single boost::variant type into two different ones: one for the master and one for the slave state machine. And each boost::variant type will just be forwarded to the appropriate process_event method of the corresponding state machine. Doing so, will also prevent unnecessary template invocations for each event type on the corresponding state machine. Maybe this will also reduce the memory consumption...
If your variant "knows" less types and thus provokes less different process_event instantiations within one TU, yes.
What is your opinion about this two putative solutions?
I suppose it depends on your use case. I personally tend to build several smaller state machines. I find them easier to understand and more likely to be reused. Sometimes I go as far as hiding each fsm in the cpp of a different class. Then I make sure each class follows a given, small interface. This way, they are easier to exchange with others or to combine. Sure I lose the tight coupling of submachines, but I don't think I make a bad deal. But again, this is a matter of taste and of your personal use case.
Best regards (viele grüsse),
Rafael
Viele Grüße, Christophe