0

I have two events that are being fired and handled by two event handlers. In EventHandler2 a boost::thread is started. In EventHandler2 the application is waiting for this thread to finish by calling join() on it.

This has workled well on fast computers, because the event that started the thread was always fired first, before the other event that caused the application to ait for the join(). However, on old machines, the events are fired in different order (because there is some heavy computing to be done before EventHandler2 is called). So EventHandler1 is called first and does not wait, since the join() immediately returns (thread has not been started yet, becuase the 2nd event was not fired). whats the best I can do here? Do I need to lock a mutex and then wait for it before I call the join(). This way I make sure that the thread is started before a join() is called on it. Whats the best pattern to use in this case? Thank you!

tzippy
  • 6,458
  • 30
  • 82
  • 151

2 Answers2

0

It seems like you need to specify an order or priority of execution. From your question it also seems like you have heterogenous threads (in terms of behavior) so I am going to suggest synchronization. A mutex alone will likely not be enough (although in many implementations a mutex is the same as a binary semaphore). An easy way to do this is with monitors. https://en.wikipedia.org/wiki/Monitor_(synchronization)

Curious
  • 20,870
  • 8
  • 61
  • 146
0

To paraphrase the problem (let me know if I've misunderstood): you've got two event handlers (A and B) that will be executed, and it's not guaranteed which one will be executed first -- the execution ordering might be (A,B) or it might be (B,A)... but in either case you'd like the system to behave as if the handlers had been executed in (A,B) order.

The way I'd approach this problem is to make the handlers smarter, so that they can detect when the "wrong" handler has been executed first and deal with it gracefully. In particular, when your B handler executes, it should have a way to detect if the A handler has already executed. If B sees that A has already executed, then B can do its normal thing (i.e. join() the thread) and all is well. On the other hand, if B finds that A has not already executed, then B should instead just set a flag (perhaps a boolean in a data structure that A will have access to?) so that when the A handler runs later on, it will know that the B handler has already been-and-gone, and therefore A will know that it cannot rely on B to do any cleanup work. That is, when A runs, it will check the flag; if the flag was set by B, then A will also call join() before returning, since A knows that B won't be doing it later (or, alternatively, perhaps A could schedule another B event, if you prefer not to call join() directly from the A handler).

If your A and B handlers are both being called in the same thread, then this should be straightforward to do; if A and B are being called from different threads, you'll need to be more careful to do the flag-handling in a thread-safe manner (e.g. using std::atomic or similar).

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234