Fsdfdsg
Fsdfdsg

Reputation: 21

How to solve Producer-Consumer using winapi events in c++?

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

Answers (2)

Rama
Rama

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

RbMm
RbMm

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

Related Questions