Windows MultiThreading : Producer-Consumer with a Bounded Buffer

·

Producer-Consumer with a Bounded Buffer

A variation of the producer-consumer problem involves multiple producers and consumers sharing a finite-sized buffer. The challenge is to prevent producers from adding when the buffer is full and to prevent consumers from removing when the buffer is empty.

Explanation

  • emptySlots semaphore keeps track of available slots in the buffer.
  • fullSlots semaphore tracks items in the buffer.
  • mutex ensures mutual exclusion when accessing the buffer.

These implementations demonstrate the flexibility and power of semaphores, mutexes, and synchronization patterns in solving classical concurrency problems. Let me know if you’d like further explanations or additional examples!

Implementation

#include <iostream>
#include <windows.h>
#include <thread>
#include <vector>
#include <queue>

const int BUFFER_SIZE = 5;
std::queue<int> buffer;

// Semaphores
HANDLE emptySlots;
HANDLE fullSlots;
HANDLE mutex;

void producer(int id) {
    int item = 0;
    while (true) {
        Sleep(1000); // Simulate production time
        WaitForSingleObject(emptySlots, INFINITE);
        WaitForSingleObject(mutex, INFINITE);

        buffer.push(++item);
        std::cout << "Producer " << id << " produced item " << item << ". Buffer size: " << buffer.size() << "\n";

        ReleaseMutex(mutex);
        ReleaseSemaphore(fullSlots, 1, NULL);
    }
}

void consumer(int id) {
    while (true) {
        WaitForSingleObject(fullSlots, INFINITE);
        WaitForSingleObject(mutex, INFINITE);

        int item = buffer.front();
        buffer.pop();
        std::cout << "Consumer " << id << " consumed item " << item << ". Buffer size: " << buffer.size() << "\n";

        ReleaseMutex(mutex);
        ReleaseSemaphore(emptySlots, 1, NULL);
        Sleep(1500); // Simulate consumption time
    }
}

int main() {
    emptySlots = CreateSemaphore(NULL, BUFFER_SIZE, BUFFER_SIZE, NULL);
    fullSlots = CreateSemaphore(NULL, 0, BUFFER_SIZE, NULL);
    mutex = CreateMutex(NULL, FALSE, NULL);

    if (emptySlots == NULL || fullSlots == NULL || mutex == NULL) {
        std::cerr << "Failed to create semaphores or mutex.\n";
        return 1;
    }

    std::vector<std::thread> producers, consumers;
    for (int i = 0; i < 3; ++i) {
        producers.emplace_back(producer, i + 1);
    }
    for (int i = 0; i < 2; ++i) {
        consumers.emplace_back(consumer, i + 1);
    }

    for (auto& p : producers) {
        p.join();
    }
    for (auto& c : consumers) {
        c.join();
    }

    CloseHandle(emptySlots);
    CloseHandle(fullSlots);
    CloseHandle(mutex);

    return 0;
}

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *