I would like to ask you a question regarding which concurrency facility (CMutex, CSemaphore, CEvent) should I choose, to make a C++/MFC, application multi-threaded.
It is a real time, machine vision application, that is required now to execute concurrently and it needs refactoring, from it’s previous single-threaded status.
A single iteration of my workflow is the following. I have 2 producers A,B (MFC Workers) that need to fill two separate data structures (1 each). A third thread, a consumer (MFC Worker as well) is blocked, until both data become available from A and B. Then, producers A and B must block (each, upon their data completion), C must wake up, perform a calculation, unblock A and B to continue and become blocked again, waiting for the next segments.
- I must not use queues (Actor-like) – the blocking is a requirement
🙁 - I tried CEvent and it works. AutoResetEvents for A,B to unblock a
CMultiLock call on C and then a ManualResetEvent->Set() from C, to
unblock A and B waiting on the latter event. My concern is when to
reset this event (in case e.g. A miss the whole Set and then Reset.) - Do semaphores with plurality of 2 may stand for a better solution?
Best regards.
C must wait for two things to happen, so the most logical thing is that it waits for two auto-reset
CEventobjects: one set by A and one by B.When C is done, A and B must each then wait for a notification. Since there are two threads, and both must wake up, the natural thing is to use another pair of auto-reset
CEventobjects, one for each of A and B. C can then set both when it is done.A semaphore with a count of 2 would work for waking C — C waits twice, and each of A and B notify — but this means that C must wake up after the first notification in order to wait for the second, which is less than ideal.
Using a semaphore with a count of 2 for waking A and B afterwards has the potential for stolen wake-ups and confusion. C signals the semaphore twice. A wakes and takes a signal, does its processing and notifies C, and then waits on the semaphore again. Since B hasn’t yet woken up, the semaphore is still available, so A takes it again. Meanwhile B is not stuck, since it won’t get another signal, and C is stuck, since it will wait for the next value from B.
An alternative is to use the Windows Condition Variable API rather than events, but there doesn’t seem to be an MFC wrapper for that. See http://msdn.microsoft.com/en-us/library/ms682052%28VS.85%29.aspx