Reputation: 1195
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.
Best regards.
Upvotes: 2
Views: 336
Reputation: 12237
You can simply use CEvent objects and than WaitForMultipleObjects() which allows you to wait on both objects via the third parameter 'bWaitAll'.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx
Upvotes: 0
Reputation: 20576
I propose a signalling system, using a counter protected by a mutex. This keeps all the synchronization work confined to one small class that does notheing else.
A starts
A writes A-Data
A signals
A stops
B starts
B writes B-Data
B signals
B stops
C starts
C reads A-Data and B-Data
C starts A, B
C stops
*Signal Class*
Mutex protected counter attribute
Receives signal for A, increment counter
Receives signal for B, increment counter
IF counter equals 2, clear counter and start C
Upvotes: 0
Reputation: 68631
C must wait for two things to happen, so the most logical thing is that it waits for two auto-reset CEvent
objects: 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 CEvent
objects, 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
Upvotes: 2
Reputation: 231313
I would go for a slight modification of your option 2 - use a CMultiLock on two events to block C; then use another pair of events to block A and B. C would set two auto-reset events to wake up each of A and B. Then you no longer have the race for the reset.
Upvotes: 2