Re: [Boost-users] [statechart] : asynchronous_state_machine - access member functions
Hi Andreas, Your solution will not work in my application. I use an io-framework which has some requirements that could not be fullfilled with the creation process of an asynchronous_state_machine. asynchronous_state_machine is derived from state_machine - does this mean that asynchronous_state_machine provides only a thread-safe access to state_machine (acts as a wrapper)? In my application I've three event sources (io-device, UNIX-signal handler, trigger which periodically produces events). Each event source runs in ist own thread. I could use a state_machine and synchronize the insertion of events (process_event() function) via a mutex. Would asynchronous_state-machine provide a preformance benfit in this case? Would it be an adequat solution to queue the events from the three event sources in a thread-safe queue (producer-consumer pattern)? The threads providing events act as producer threads) and should not be blocked and the processing of the events (calling state_machine::process_event()) will be done snychronous (maybe by one consumer thread). Regards,Oliver
Oliver.Kowalke@qimonda.com wrote:
Hi Andreas,
Your solution will not work in my application. I use an io-framework which has some requirements that could not be fullfilled with the creation process of an asynchronous_state_machine.
Could you please expand on this?
asynchronous_state_machine is derived from state_machine - does this mean that asynchronous_state_machine provides only a thread-safe access to state_machine (acts as a wrapper)?
This might be a little counter-intuitive, but asynchronous_state_machine itself is not thread-safe. It is the fifo_worker inside the fifo_scheduler that does all the locking and waiting. That's why you cannot create asynchronous_state_machine subclass objects yourself but must let fifo_scheduler create them for you.
In my application I've three event sources (io-device, UNIX-signal handler, trigger which periodically produces events). Each event source runs in ist own thread. I could use a state_machine and synchronize the insertion of events (process_event() function) via a mutex.
That's bad practice performance-wise and can easily lead to deadlocks.
Would asynchronous_state-machine provide a preformance benfit in this case?
Almost certainly. fifo_scheduler has an internal event queue and locks are only taken for push and pop operations. Events are processed outside locks, which improves performance.
Would it be an adequat solution to queue the events from the three event sources in a thread-safe queue (producer-consumer pattern)?
See above, that's essentially the job of fifo-scheduler Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
Hello Andreas,
Your solution will not work in my application. I use an io-framework which has some requirements that could not be fullfilled with the creation process of an asynchronous_state_machine.
Could you please expand on this?
My io-framework (sockets) requiers that the service handler is derived from enable_shared_from_this and will be managed by an shared_ptr. This service handler is invoked if a message is delivered over tne network and implements a state machine in order to process the network message (communication protocol). Because asynchronous_state_machine is created by fifo_scheduler::create_processor it will not work with the io-framework. I could split the class into a io service handler class which aggregates a state_machine but this leads to other problems because I need a way to call io sevice handler functions from several states of the fsm.
In my application I've three event sources (io-device, UNIX-signal handler, trigger which periodically produces events). Each event source runs in ist own thread. I could use a state_machine and synchronize the insertion of events (process_event() function) via a mutex.
That's bad practice performance-wise and can easily lead to deadlocks.
Why deadlocks? I protect the state machine with a mutex. So only one thread has access to the state machine at the same time. I believe that you use also a mutex in the fifo_scheduler in order to synchronize access to the state machine -right?
Would asynchronous_state-machine provide a preformance benfit in this case?
Almost certainly. fifo_scheduler has an internal event queue and locks are only taken for push and pop operations. Events are processed outside locks, which improves performance.
Using sc::state_machine together with a multithreaded queue which stores push operations (meaning sc::state_machine::process_event() invokations) should also model your implementation. Producer threads put function objects into the queue and one consumer thread dequeues the functions objects and invokes operator() on the function object (which leads to inserting an event into fsm via process_event()). May this work? Regards, Oliver
Without seeing code it is of course difficult to make good suggestions, so I'm just giving some general hints that might or might not work in your situation.
My io-framework (sockets) requiers that the service handler is derived from enable_shared_from_this and will be managed by an shared_ptr.
You could multi-inherit a new class from asynchronous_state_machine and enable_shared_from_this. You'd then derive all your FSMs from this class.
This service handler is invoked if a message is delivered over tne network and implements a state machine in order to process the network message (communication protocol). Because asynchronous_state_machine is created by fifo_scheduler::create_processor it will not work with the io-framework.
All FSMs could be registered with the io framework on creation (e.g. in the ctor of the new class above) and deregistered on destruction.
I could split the class into a io service handler class which aggregates a state_machine but this leads to other problems because I need a way to call io sevice handler functions from several states of the fsm.
This could be achieved through boost::function objects passed to the ctor of each FSM.
In my application I've three event sources (io-device, UNIX-signal handler, trigger which periodically produces events). Each event source runs in ist own thread. I could use a state_machine and synchronize the insertion of events (process_event() function) via a mutex.
That's bad practice performance-wise and can easily lead to deadlocks.
Why deadlocks? I protect the state machine with a mutex. So only one thread has access to the state machine at the same time.
The danger of deadlocks arises when the state_machine itself needs to send events to other similarly protected state_machines or back to the io service handler. You should be safe deadlock-wise when the state_machine subclass object does not proactively communicate with the outside world.
I believe that you use also a mutex in the fifo_scheduler in order to synchronize access to the state machine -right?
Not quite. I'm using a mutex to protect the queue in fifo_scheduler (in reality the mutex & queue are in fifo_worker but we can pretend that they are in fifo_scheduler for this discussion). The worker thread inside fifo_scheduler is the one and only thread that will ever access any FSMs created through the scheduler. So there's no need to lock to access a FSM.
Would asynchronous_state-machine provide a preformance benfit in this case?
Almost certainly. fifo_scheduler has an internal event queue and locks are only taken for push and pop operations. Events are processed outside locks, which improves performance.
Using sc::state_machine together with a multithreaded queue which stores push operations (meaning sc::state_machine::process_event() invokations) should also model your implementation. Producer threads put function objects into the queue and one consumer thread dequeues the functions objects and invokes operator() on the function object (which leads to inserting an event into fsm via process_event()). May this work?
Sure, that's pretty much what fifo_scheduler does, besides managing the lifetime of the FSMs it hosts. If you don't yet have a thread-safe worker class sitting around somewhere you might want to have a look at statechart::fifo_worker. HTH, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
participants (2)
-
Andreas Huber
-
Oliver.Kowalke@qimonda.com