I am trying to understand the code from the tutorial. I changed the code a little, see below. There are two problems, I would appreciate any help to find out what is wrong.
- the program never stops, I have to kill it.
- the output looks different than I expect, specifically, each value from 0 to 9 is deposited and fetched twice (I expect once deposited and once fetched for each value).
Output sample:
Producer deposited value 0.
Consumer fetched value 0.
Producer deposited value 0.
Consumer fetched value 0.
Producer deposited value 1.
Producer deposited value 1.
Consumer fetched value 1.
Producer deposited value 2.
...
Code:
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>
class BoundedBuffer {
public:
int * buffer;
int capacity;
int front;
int rear;
int count;
std::mutex mtx;
std::condition_variable not_full;
std::condition_variable not_empty;
BoundedBuffer (int capacity)
: capacity(capacity), front(0), rear(0), count(0)
{
buffer = new int[capacity];
}
~BoundedBuffer () {
delete [] buffer;
}
void deposit (int data) {
std::unique_lock<std::mutex> lck(mtx);
not_full.wait(lck, [this] () {
return count != capacity;
});
buffer[rear] = data;
rear = (rear + 1) % capacity;
++count;
std::cout << "Producer deposited value " << data << ".\n";
lck.unlock();
not_empty.notify_one();
}
int fetch () {
std::unique_lock<std::mutex> lck(mtx);
not_empty.wait(lck, [this] () {
return count != 0;
});
int result = buffer[front];
front = (front + 1) % capacity;
--count;
std::cout << "Consumer fetched value " << result << ".\n";
lck.unlock();
not_full.notify_one();
return result;
}
};
void consumer (int id, BoundedBuffer & buffer) {
for(int i = 0; i < 10; ++i) {
int value = buffer.fetch();
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
void producer (int id, BoundedBuffer & buffer) {
for(int i = 0; i < 10; ++i) {
buffer.deposit(i);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main () {
BoundedBuffer buffer (10);
std::thread c0 (consumer, 0, std::ref(buffer));
std::thread c1 (consumer, 1, std::ref(buffer));
std::thread c2 (consumer, 2, std::ref(buffer));
std::thread p0 (producer, 0, std::ref(buffer));
std::thread p1 (producer, 1, std::ref(buffer));
c0.join();
c1.join();
c2.join();
p0.join();
p1.join();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire