Boost logo

Boost Users :

From: Philippe DAVID (philippe.a.david_at_[hidden])
Date: 2007-11-21 05:25:59


Quoting Andreas Huber <ahd6974-spamboostorgtrap_at_[hidden]>:

> "Philippe DAVID" <philippe.a.david_at_[hidden]> wrote in message
> news:20071120173440.x0inzib4w0sssow0_at_mail.sogeti.com...
>>>> 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.
>>
>> Ok, let me give you more details about what I'm doing. I am writing a
>> library
>> which is used by other devs in the team. Basically, this library handles
>> the
>> internals of a protocol and for the dev who is using it, it provides a
>> class
>> called Handler. This Handler class contains callbacks methods and action
>> methods. For instance, receiveMessage() is called when a new message has
>> been
>> completely received and sendMessage() sends a message. The user will
>> override
>> the callback methods to write its own reaction code to events.
>>
>> My code and the FSM are in a class called Connection. For each tcp
>> connection,
>> there is exactly one instance of Connection linked to one instance of a
>> user
>> class derived from Handler. This means that the user code only interacts
>> with
>> the state machine through methods I wrote.
>
> Ok, that sounds good. So I take it there's no human operator involved
> anywhere, right?

No, no human operator here. The term "user" was misleading, sorry about that.

>
>> As I said, I am using ACE, and the ACE Reactor (event demultiplexer based
>> on
>> select), which means I am called by the Reactor whenever something happens
>> on
>> the socket. My current design is to process an event in the state machine
>> when
>> I am called by the reactor (this reactor is single threaded and that's
>> what we
>> want here).
>
> ST renders many of my earlier comments invalid. Wrong assumption, sorry.
>
>> Depending on the state of my machine I will try to read from the
>> socket, and depending on the result i will eventually post a
>> "MessageComplete"
>> event. The reaction to MessageComplete calls Handler::receiveMessage().
>> From
>> that point if I want the user to be able to call action methods from
>> within the
>> callbacks, I need to use post_event in them.
>> My problem is that if I want to write an action method "close", and if I
>> use
>> post_event in it, then close can't be called from outside a callback.
>
> Right. IIUC, then Handler completely insulates the user code from the
> state_machine? If so, then you could solve the problem quite centrally in
> Handler, no? Before you call Handler::receiveMessage() you set a private
> bool in Handler and ensure that its reset when receiveMessage returns.
> Moreover, you'd have a private method called e.g. Handler::sendEvent(),
> which calls either process_event or post_event based on whether the bool is
> true or not. Not exactly award-winning software engineering, I know.
> But it would at least solve the problem without duplicating that darn check
> everywhere.

Exactly. Hence my initial question "does statechart can give this
boolean value"
instead of dealing with it myself.
It's no big deal actually if the state_machine::is_processing() method
does not
exist, but it would be convenient to have it.

Thank you for your time Andreas, the discution was informative.

Best regards
Philippe


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