Boost logo

Boost Users :

From: Andreas Huber (ahd6974-spamboostorgtrap_at_[hidden])
Date: 2007-11-19 13:36:09


Hi Philippe

> My state machine is coupled to a connection on which I must comply with
> some
> protocol. My layer is a middleware. Each time I have something
> interesting,
> like data or events, I call a user-supplied handler on a corresponding
> method
> from a react method of the state machine.

It's *usually* not a good idea to make *direct* callbacks to client code
from within the state machine, for the reason I'll outline below. Client
code can do anything, including calling process_event() again on the same
state machine, which is not permitted. I say usually because there are
perfectly sane ways to do it: You restrict what said client code can do,
e.g. the code could act as a simple plug-in (do some calculation, the result
of which is immediately returned to the state machine).

> If the user wants to close the connection I have the problem I described
> because:
> - either he decides to close the connection from a callback, which means
> the
> state machine is in the middle of processing the event which caused the
> call to
> the handler, then I must use post_event
> - or he decided to close the connection based on an event that didn't
> come from
> the connection, in that case I must use process_event.

I assume by "user" you mean a human operator of your system. If so, then
what you're doing is almost certainly bad practice. In the best case your
system is totally unresponsive to any other events while it waits for the
callback to return from client code (IIUC, this only happens when the human
operator clicks a button or some such). Under certain circumstances you want
exactly that, but be aware that in an MT environment you'd have to protect
your FSM with a mutex and other threads will simply wait for said mutex to
become available before they can proceed to offload their event. This
results in bad scalability and takes away any chance for the processing of
say emergency events from the outside world.

> In the simple case I could also provide 2 close methods for the handler,
> one
> that must be called in callbacks and one for the other methods of handler.
> I
> don't think this is a clean way to solve this issue. Each method in my
> interface would have 2 versions, and the stability becomes really weak
> because
> calling the wrong method at the wrong place results in a crash.

Right.

> At this point,
> maybe my design is weak, and I shouldn't call the handlers callback
> directly
> from the react methods.

Yes, I believe so.

> Instead I could use an event queue to talk to the
> handler. In the react method I would post events to the queue, and make
> sure I
> dequeue it from outside the state machine.

This is what you usually do. The library offers support for this with
asynchronous_state_machine and fifo_scheduler. While these classes are
fairly minimal they might still be the perfect fit for your problem. Instead
of calling the user-supplied callbacks directly you'd have fifo_scheduler
call them for you with fifo_scheduler::queue_work_item().

> But it involves (much) more work...

If the classes I mentioned work for you then I don't think it's really that
much more work.

Please let me know how that works out.

Regards,

-- 
Andreas Huber
When replying by private email, please remove the words spam and trap
from the address shown in the header. 

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net