It is first time when I’m synchronizing threads using events. My code works fine. But as I experienced it can look fine but have obvious bug which will be really hard to find when I use this concept in bigger project.
So I just want to ask if this way of using events to synchronize threads looks fine for you?
The idea is that we have GetSymbol function which can be called only from main thread. Server thread need to ask main thread for results from this function.
#include <windows.h>
#include <process.h>
#include <stdio.h>
HANDLE symbol_need, symbol_ready, end;
int symbol_container;
int GetSymbol()
{
// Only main thread can use this function.
static int i = 0;
return ++i;
}
void Server(void* p)
{
printf("Ask for first symbol.\n");
SetEvent(symbol_need);
DWORD wait_result;
wait_result = WaitForSingleObject(symbol_ready, INFINITE);
if(WAIT_OBJECT_0 == wait_result)
{
ResetEvent(symbol_ready);
printf("First symbol: %i\n", symbol_container);
} else {
printf("Something went wrong.\n");
}
printf("Ask for second symbol.\n");
SetEvent(symbol_need);
wait_result = WaitForSingleObject(symbol_ready, INFINITE);
if(WAIT_OBJECT_0 == wait_result)
{
ResetEvent(symbol_ready);
printf("Second symbol: %i\n", symbol_container);
} else {
printf("Something went wrong.\n");
}
printf("OK, finish it.");
SetEvent(end);
}
int main(int argc, char* argv[])
{
symbol_need = CreateEvent( NULL, FALSE, FALSE, NULL );
symbol_ready = CreateEvent( NULL, FALSE, FALSE, NULL );
end = CreateEvent( NULL, FALSE, FALSE, NULL );
_beginthread(Server, 0, NULL);
DWORD wait_result;
while(1)
{
wait_result = WaitForSingleObject(symbol_need, 100);
if(WAIT_OBJECT_0 == wait_result)
{
ResetEvent(symbol_need);
symbol_container = GetSymbol();
SetEvent(symbol_ready);
}
wait_result = WaitForSingleObject(end, 100);
if(WAIT_OBJECT_0 == wait_result)
{
break;
}
}
return 0;
}
Yes, this code is correct.
This example is useful to see how events work. However, there is no need to go reinventing the wheel when you are writing production code. For example, the interaction you described can be elegantly modeled using concurrent data structures like the ones in the Intel TBB library e.g. concurrent_bounded_queue.