Reputation: 21
I need to solve Producer-Consumer problem in c++ using primitive synchronization objects - events, I already wrote this code
static int g_x = 0;
HANDLE hEvent1;
HANDLE aThread[2];
DWORD ThreadID;
//tread 1
void Producer()
{
for (int i = 0; i < 100; ++i)
{
WaitForSingleObject(hEvent1, INFINITE);
g_x = i;
SetEvent(hEvent1);
}
}
//thread 2
void Consumer()
{
for (;;)
{
WaitForSingleObject(hEvent1, INFINITE);
SetEvent(hEvent1);
}
}
int createthreads() {
hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL);
// Create worker threads
aThread[0] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL, 0, &ThreadID);
aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID);
}
int main() {
createthreads();
}
This code doesn't work correctly: I have Infinite cycle
How can I fix this code to get in console numbers from 0
to 99
?
Upvotes: 1
Views: 1514
Reputation: 3305
You need another event to syncronize this two threads.
Also I set the initial state of two events to FALSE
, and I send a start event to the producer thread on the main
.
This way you can control when and how the process is started.
And Offtopic, createthreads
must return a value.
static int g_x = 0;
HANDLE hEvent1;
HANDLE hEvent2;
HANDLE aThread[2];
DWORD ThreadID;
//tread 1
void Producer()
{
for (int i = 0; i < 100; ++i)
{
WaitForSingleObject(hEvent1, INFINITE);
g_x = i;
SetEvent(hEvent2);
}
}
//thread 2
void Consumer()
{
for (;;)
{
WaitForSingleObject(hEvent2, INFINITE);
SetEvent(hEvent1);
}
}
int createthreads() {
hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
// Create worker threads
aThread[0] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL, 0, &ThreadID);
aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID);
return 0;
}
int main() {
createthreads();
SetEvent(hEvent1);
}
Upvotes: 1
Reputation: 33716
exist many ways implement this task, one possible - need use event pair - 2 events.
struct EventPair
{
HANDLE hLowEvent, hHighEvent;
~EventPair()
{
if (hHighEvent) CloseHandle(hHighEvent);
if (hLowEvent) CloseHandle(hLowEvent);
}
EventPair()
{
hLowEvent = 0, hHighEvent = 0;
}
DWORD Create()
{
return (hLowEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) &&
(hHighEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ? NOERROR : GetLastError();
}
};
struct SharedData : EventPair
{
int _x;
bool _quit;
SharedData()
{
_x = 0;
_quit = false;
}
static DWORD WINAPI _Producer(void* This)
{
reinterpret_cast<SharedData*>(This)->Producer();
ExitThread(0);
}
void Producer()
{
for (int i = 0; ; )
{
_x = i++;
if (i == 100)
{
_quit = true;
}
SetEvent(hLowEvent);
if (_quit)
{
return;
}
WaitForSingleObject(hHighEvent, INFINITE);
}
}
static DWORD WINAPI _Consumer(void* This)
{
reinterpret_cast<SharedData*>(This)->Consumer();
ExitThread(0);
}
void Consumer()
{
for(;;)
{
WaitForSingleObject(hLowEvent, INFINITE);
DbgPrint("%u\n", _x);
if (_quit)
{
return;
}
SetEvent(hHighEvent);
}
}
};
void testPC()
{
SharedData sd;
if (!sd.Create())
{
HANDLE hThreads[2] = {};
if (hThreads[0] = CreateThread(0, 0, SharedData::_Producer, &sd, 0, 0))
{
if (hThreads[1] = CreateThread(0, 0, SharedData::_Consumer, &sd, 0, 0))
{
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
CloseHandle(hThreads[1]);
}
else
{
sd._quit = true;
SetEvent(sd.hHighEvent);
WaitForSingleObject(hThreads[0], INFINITE);
}
}
CloseHandle(hThreads[0]);
}
}
Upvotes: 0