I want to use boost msm state machine but i am having a hard time imagining how it works. Let say we only have 2 states (s1, s2) and to go from s1 to s2 you need event e1 to be fired and to bo back you need another one e2.
e1 and e2 can only be fired from within s1 and s2 respectively.
Now in main() I start by starting the statemachine (start()) then ill have a while loop that every 1 min will go back to the state machine but have to pick up from where it left.i.e.
main()
{
MSM.start(); //start state machine
while (a_condition)
{
ProcessInputsfromIO();
Go_backtoStatemachine(); //how can i do this?
delay(1min)
}
MSM.stop();
}
So basically when a state finishes executing, the statemachine will exit, then ill have a delay of 1 minutes, then the while loop will need to take me back to the state I was before I exit, or I think that's how we should implement a state machine.
Is what I am asking for out of the ordinary? If yes then how do people implement a non-blocking state machine? if no, then how can I implement Go_backtoStatemachine()?
There is a fairly simple example here:
MSM Simple Tutorial
A state machine is an abstract concept. It has states, events, etc. It does not really have a concept of blocking, non blocking, etc. Within the framework of Boost MSM you can call start() to enter the initial state, process_event() to inject events, and stop() to stop. The state machine simply captures system state and can call some functions as the system changes state. How you would use it is very application dependant.
MSM has not any knowledge of threads, so when start() or process_event(MyEvent()) are called, they are executed on the current thread. It's possible to defer the event processing to a later moment though (which is still NOT thread-safe), as explained on the docs (https://www.boost.org/doc/libs/1_75_0/libs/msm/doc/HTML/ch03s05.html#d0e2668):
Enqueueing events for later processing
Calling process_event(Event const&) will immediately process the event
with run-to-completion semantics. You can also enqueue the events and
delay their processing by calling enqueue_event(Event const&) instead.
Calling execute_queued_events() will then process all enqueued events
(in FIFO order). Calling execute_single_queued_event() will execute
the oldest enqueued event.
You can query the queue size by calling get_message_queue_size().
In the question's example then, you can
enqueue the events inside ProcessInputsfromIO as
void ProcessInputsfromIO(){
somethingToDo();
myfsm.enqueue_event(myEvent1());
somethingElseToDo();
etc();
}
Go_backtoStatemachine() becomes simply myfsm.execute_queued_events()
Related
First of all, I'd like to clarify that by ASIO objects I mean a simple timer for the time being, but further down the line I want to create a state machine to deal with sockets and data transmission.
I have been exploring the Boost SML library for about a few weeks now and trying out different things. I quite like it, however the documentation doesn't help in my use case and its source is not exactly inviting for someone still fairly new to metaprogramming.
For the time being, I'd like to create a state machine that manages an ASIO timer (to wait asynchronously). The interface would provide a start call where you can tell it how long it should wait, a cancel call (to cancel an ongoing wait), and some callback to be invoked when the timer fires.
I have already achieved this in one way, following both sml examples in this repository and it works well - I have a class which manages the timer and contains a state machine. The public interface provides means to inject the appropriate events into the FSM and query its state. The private interface provides means to start and stop the timer. The FSM class is a friend to the controller so it has access to the private functions.
However I was wondering if there is a way to take some of the controller functionality and move it into the FSM - it would hold all ASIO objects and run the io_context/io_service in a thread it has spawned.
(1) First problem I'd encounter is the fact that the state machine is copied - ASIO objects don't allow this, but this can be worked around by wrapping them in shared pointers.
(2) Next is, sending events to the FSM from within. I figured out how to do it from actions by obtaining a callable boost::sml::back::process<> object and using this to "post" the event to the queue, but this would be useless from an ASIO handler as this by default would not be invoked from an action. I suppose a way around this is to capture the callable into the timer handler with a lambda, like this:
// Some pseudo code (this would all be done in one class):
// Transition table
"idle"_s + event<Wait> / start_waiting = "waiting"_s
// Events
struct Wait { std::chrono::seconds duration; };
struct Cancel {};
struct Expire {};
// Actions
std::function<void(Wait const&, boost::sml::back::process<Cancel, Expire>)> start_waiting =
[this] (Wait const& e, boost::sml::back::process<Cancel, Expire> p) {
run_timer(e, p);
};
// Private function
void run_timer(Wait const& e, boost::sml::back::process<Cancel, Expire>& p) {
m_timer->expires_after(e.duration);
auto timerHandler = [&p] (asio::error_code const& e) {
if (e == asio::error::operation_aborted)
p(Cancel{});
else
p(Expire{});
};
timer->async_wait(timerHandler);
}
But this feels like a bit of a botch.
(3) The last thing that worries me is how the state machine will handle threads. Obviously the timer handler will be executed in its own thread. If that posts an event to the queue of the FSM, will that event be processed by the same thread that posted it? I'm assuming yes, because I can't see any mentions of threads (other than thread safety) in the header. This will dictate how I go about managing the threads' lifetime.
Any tips on alternative ways to architect this, and their pros and cons, would be of great help.
I'm currently trying to get my hands on boost::asio strands. Doing so, I keep reading about "invoking strand post/dispatch inside or outside a strand". Somehow I can't figure out how inside a strand differs from through a strand, and therefore can't grasp the concept of invoking a strand function outside the strand at all.
Probably there is just a small piece missing in my puzzle. Can somebody please give an example how calls to a strand can be inside or outside it?
What I think I've understood so far is that posting something through a strand would be
m_strand.post(myfunctor);
or
m_strand.wrap(myfunctor);
io_svc.post(myfunctor);
Is the latter considered a call to dispatch outside the strand (as opposed to the other being a call to post inside it)? Is there some relation between the strand's "inside realm" and the threads the strand operates on?
If being inside a strand simply meant to invoke a strand's function, then the strand class's documentation would be pointless. It states that strand::post can be invoked outside the strand... That's precisely the part I don't understand.
Even I had some trouble in understanding this concept, but became clear once I started working on libdispatch. It helped me map things with asio better.
Now lets see how to make some sense out of strand. Consider strand as a serial queue of handlers which needs to be executed.
Now, where does these handlers get executed ? Within the worker threads.
Where did these worker threads come from ? From the io_service object you passed while creating the strand.
Something like:
asio::strand s(io_serv_obj);
Now, as you must be knowing, the io_service::run can be called by a single thread or multiple threads. The threads calling the run method of the io_serv_obj are the worker threads for that strand in our case. So, it could be either single threaded or multithreaded.
Coming back to strands, when you post a handler, that handler is always enqueued in the serial queue which we talked about. The worker threads will pick up the handler from the queue one after the other.
Now, when you do a dispatch, asio does some optimization for you:
It checks whether you are calling it from inside one of the worker thread or from some other thread (maybe of some other io_service instance). When it is called outside the current execution context of the strand, thats when it is called outside the strand. So, in the outside case, the dispatch will just enqueue the handler like post when there are other handlers waiting in the queue or will call it directly when it can guarantee that it will not be called concurrently with any other handler from that queue that may be running in one of the worker threads at that moment.
UPDATE:
As noted in the comments section, inside means called within another handler i.e for eg: I posted a handler A and inside that handler, I am doing a dispatch of another handler. Now, as would be explained in #2, if there are no other handlers waiting in the strands serial queue, the dispatch handler will be called synchronously. If this condition is not met, that means, the dispatch is called from outside.
Now, if you call dispatch from outside of the strand i.e not within the current execution context, asio checks its callstack to see if any other handler present in its serial queue is running or not. If not, then it will directly call that handler synchronously. So, there is no cost of enqueueing the handler (I think no extra allocation will be done as well, not sure though).
Lets see the documentation link now:
s.dispatch(a) happens-before s.post(b), where the former is performed
outside the strand
This means that, if dispatch was called from some outside the current run OR there are other handlers already enqueued, then it needs to enqueue the handler, it just cannot call it synchronously. Since its a serial queue, a will get executed before b.
Had there been another call s.dispatch(c) along with a and b but before a and b(in the mentioned order) enqueued, then c will get executed before a and b, but in no way b can get executed before a.
Hope this clears your doubt.
For a given strand object s, running outside s implies that s.running_in_this_thread() returns false. This returns true if the calling thread is executing a handler that was submitted to the strand via post(), dispatch(), or wrap(). Otherwise, it returns false:
io_service.post(handler); // handler will run outside of strand
strand.post(handler); // handler will run inside of strand
strand.dispatch(handler); // handler will run inside of strand
io_service.post(strand.wrap(handler)); // handler will run inside of strand
Given:
a strand object s
a function object f1 that is added to strand s via s.post(), or s.dispatch() when s.running_in_this_thread() == false
a function object f2 that is added to strand s via s.post(), or s.dispatch() when s.running_in_this_thread() == false
then the strand provides a guarantee of ordering and non-concurrency, such that f1 and f2 will not be invoked concurrently. Furthermore, if the addition of f1 happens before the addition of f2, then f1 will be invoked before f2.
I have a C++ program that uses overlapped IO for network communication. The main thread has a loop that calls SleepEx(5, true);. There are also two TCP sockets. I assume that the completion callbacks are called during the alertable wait. Assume also that by the time SleepEx gets called both of my TCP connections have received some data. Now the question is what happens if the first completion callback takes longer than 5ms? Does the SleepEx return after calling the first callback or does it also call the second callback? In other words does the SleepEx guarantee to call ALL of the scheduled completion callbacks? This is not clear because the documentation says it will return when at least one of the events meet...
Your code must not assume that both APCs will be called before SleepEx() returns. Conversely, it must not assume that a pending APC will not be called simply because the specified wait period has expired.
The only behaviour that you can rely upon is that if one or more APCs are pending, at least one will be executed.
Generally speaking, best practice is to wait for APCs in a loop that does nothing else, using an infinite timeout in the wait. If you need to do something periodically, you can use a waitable timer to generate an APC periodically.
Alternatively, you can use WaitForSingleObjectEx() or WaitForMultipleObjectsEx() to detect when a waitable timer or other synchronization object is triggered, while still handling APCs.
However, if you must perform some periodic action that cannot be handled in an APC or be triggered by a synchronization object, you can use nested loops: the inner loop does nothing but call the wait repeatedly (with a timeout period reduced by however long the loop has already been running) and the outer loop performs the periodic action.
If you must perform some periodic action that cannot be delayed by pending APCs, you will need to do it in a separate thread. Note that because Windows is not a real-time OS, you will still not be able to guarantee that any given action will take place within any particular timeframe, although you can reduce the risk by increasing the thread priority.
This is a question about generic c++ event driven applications design.
Lets assume that we have two threads, a "Dispatcher" (or "Engine"...) and a "Listener" (or "Client"...).
Let's assume that I write the Dispatcher code, and release it as a library. I also write the Listener interface, of course.
When the Dispatcher executes (after Listener registration)
listenerInstance.onSomeEvent();
the event handling code will actually be executed by the Dispatcher thread, so if the person that implements the Listener writes something like
void Listener::onSomeEvent() { while(true) ; }
The Dispatcher will stuck forever.
Is there a "plain old c++" (I mean no boost or libsigc++) way to "decouple" the two classes, so I can be sure that my Dispatcher will work fine whatever the Listeners does in the callbacks?
bye and thanks in advance,
Andrea
Well if the event gets invoked in the same thread (as I seem to understand can be a requirement), then there isn't much you can do about it.
If this is under a Win32 app with a message pump, you could register a windows message and call PostMessage with data representing this event and you can patch the message loop to interpret that message and call the event. What you gain is a decoupling of sorts, the event call is asynchronous (ie the event call will return no matter what). But later on when you process your messages and actually call the event, your main thread will still be stalled and nothing else will run until the event handler is ready.
Another alternative is just creating a new thread (or using a thread pool) for your call. This won't work for events that require a certain thread (ie ui updating threads). Additionally this adds synchronization overhead and thread spawning overhead AND you might starve the system of threads and/or cpu time.
But really, I don't think it's your job as the library designer to anticipate and avoid these problems. If the end-user wants to create a long event handler, let him spawn a new thread on his own. If he doesn't and just wants his specific thread to handle an event, let him. It simplifies your job and doesn't add any overhead that's not needed.
I'm afraid there's no native C++ way to do this. For windows, you can use asynchronous procedure calls (APC)
One approach could be to call the onSomeEvent into a dedicated thread. This is not 100% bullet proof but it would avoid the while(true); issue.
I hope it helps
There is a pure C++ way to achieve what you're mentioning. However, it's very ineffective. Here's a sample:
class Listener
{
bool myHasEvent;
private:
void ProcessEvent()
{
while (true)
{
if (!myHasEvent)
continue; //spin lock
// Do real processing
myHasEvent = false;
}
}
public:
void onSomeEvent() { myHasEvent = true; }
};
However, I would recommend against this approach. Instead, I would transform this into more platform-specific code. I would replace the if (!myHasEvent) continue; spin lock with a OS-specific wait routine (i.e. WaitForSingleObject on Win32) passing an Event Handle. Then, in onSomeEvent, instead of myHasEvent = true; I would set the event into signaled state (i.e. SetEvent on Win32). This would be a lot more effective because the thread wouldn't eat processor time during waiting.
Another method is the PostMessage as suggested by Blindly.
I'm writing some code with boost::asio, using asynchronous TCP connections. I've to admit that I have some doubts about it. All these regarding concurrency. Here are some:
What happens if I start two or more async_write on the same socket without waiting completion of the first one? Will the handlers (and the async_write) overlap or asio provides serialization and synchronization?
Same question of above with async_connect and async_read. In general is it safe to call these functions from different threads (I'm not talking about using different buffers, that's another problem...).
I assume from your question that you have a single instance of io_service and you want to call async_write() on it from multiple threads.
async_write() ultimately calls the post() method of io_service, which in turn takes a lock and pushes the bits to be written into a work queue, ensuring that the bits won't be written interleaved. Those bits will eventually get written out and the underlying data structure that holds them (a char array or whatever) must remain valid until you get the callback signifying that the write has completed. If you are using the exact same callback function as your completion handler, you will have no way of knowing which of the two writes resulted in that function being called and if that function does anything not thread-safe, behavior may be undefined or incorrect. A popular way to handle this situation is to have a instance of a struct that is the completion handler (just overload the call () operator): you can set the properties of the struct to denote which write it corresponds to and then consult these values when the completion handler is called.
However, absent a shared lock, you have no way of controlling which of the threads actually executes its async_write() method. In fact, even if you start up two threads and have one thread immediately call async_write() and have the other sleep for an hour and then call async_write(), you are still not assured that the OS didn't schedule your threads stupidly and execute the second thread's call first. (The example is pathological but the point is universally valid.)
The same situation applies to async_read(). You certainly can interleave calls (ie do one async_read() and then another before the completion handler is called) but there is no guarantee that the will execute in the order you intend without some external means to ensure this.
If you start two asynchronous operations on the same socket, they could occur in either order. As long as they are using different buffers it's "safe", in that it won't crash, but such behavior is almost never what you want.