
Andreas Huber wrote:
Hi Dave,
Hi Andreas, thanks for your help.
David Greene wrote:
David Greene wrote:
If I have an asynchronous state machine running in another thread and I send it an event, is there any way to have the sending thread block until the event is processed?
Yes: Add a boost::function member to the event. Have the member point to a function which calls notify_one() on a boost::condition. Have the sending thread call wait() on the condition. When processing the event inside the state_machine, call the boost::function member.
Hmm...that's rather complex, but it makes sense.
Quick follow-up: when the documentation says that FifoWorker::operator() "must only be called from exactly one thread," does that mean it must be called only from one thread at any given time (i.e. it must be protected with mutexes or other concurrency protection) or that literally only one thread may ever call it and it must always be the same thread that calls it?
The latter. fifo_worker::operator() calls terminated(), which in turn returns the bool member terminated_. This call chain is not protected by mutexes. Picture the following scenario with one fifo_worker object: 1. Thread A, which is executed on CPU 1, calls operator(). Inside operator(), terminated_ is modified and operator() returns. 2. Thread B, which is executed on CPU 2, calls operator(), after thread A has returned from operator().
Nowadays both CPUs tend to have caches. Whether or not the cache contents is guaranteed to be written back to the main memory when thread A returns depends on the architecture of your hardware. IIRC, on X86 architectures there is such a guarantee. On other architectures you might need to use mutexes or a similar concept to guarantee that thread B sees the updates of thread A.
Mutexes don't effect cache coherence. Likely there will have to be calls to special intrinsics depending on the architecture.
If it's the latter then that changes things quite dramatically and I probably want a blocking scheduler and will need to create another thread just to wait on empty and call operator() when full.
I'm not sure I understand that. You only need to create a blocking scheduler and call operator() on it, that's it. operator() will return when you call terminate() from any other thread.
Yes, what I said doesn't make sense given your solution outlined above. Hmm...I was going to use a synchronous machine due to the state access problems I outlined in another message, but now I see that won't work if terminated_ is in cacheable memory and there is no hardware coherence. For my purposes that's probably ok because we'll only run on machines with hardware coherence. Therefore if I understand you correctly, it's ok if different threads calls process_event() as long as the call (and any call to statechart routines) are guarded by mutexes to avoid the non-reentrancy problems. -Dave