I am solving a task on "producer and consumer" multithreading model. In consumer class I am trying to make a method that would get private buffer from producer object using "friend", but somewhy the code doesn't compile: 'units' is a private member of'p_c_model::Producer'. Spent a lot of time trying to fix it, but didn't succeed. Even signed up here. Please, help me fix this. Thank you in advance!
//Buffer.h
#ifndef TASK03_196_TATARINOV_23_BUFFER_H
#define TASK03_196_TATARINOV_23_BUFFER_H
#include <stack>
#include <mutex>
#include <condition_variable>
///Представляет модель "производитель и потребитель".
namespace p_c_model {
///Представляет собой класс для обмена данными между
///производителями и потребителями.
template<class T>
class Buffer {
private:
///Максимальное количество элементов в буфере.
static const size_t st_max_size = 10000;
///Контейнер для хранения элементов буфера.
std::stack<T> st;
std::mutex mu;
std::condition_variable cond;
public:
///Добавляет новый элемент в буфер.
void add(const T& newElement);
///Удалаяет верхний элемент из буфера.
T remove();
///Возвращает true, если буфер пуст.
bool empty();
};
}
#endif //TASK03_196_TATARINOV_23_BUFFER_H
//Buffer.cpp
#include "Buffer.h"
namespace p_c_model{
template<class T>
void Buffer<T>::add(const T& newElement) {
while (true) {
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker, [this](){ return st.size() < st_max_size; });
st.push(newElement);
locker.unlock();
cond.notify_all();
return;
}
}
template<class T>
T Buffer<T>::remove(){
while (true)
{
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker, [this](){ return !st.empty(); });
T top = st.top();
st.pop();
locker.unlock();
cond.notify_all();
return top;
}
}
template<class T>
bool Buffer<T>::empty(){
return st.empty();
}
}
//Producer.h
#ifndef TASK03_196_TATARINOV_23_PRODUCER_H
#define TASK03_196_TATARINOV_23_PRODUCER_H
#include <fstream>
#include "Buffer.h"
#include "Consumer.h"
namespace p_c_model{
class Producer{
private:
Buffer<std::string> units;
Buffer<unsigned int> prices;
std::ifstream fin;
std::mutex mu;
friend template class<T>
void Consumer<T>::get_buffer(Producer& pr);
public:
explicit Producer(const std::string& path);
~Producer();
void run();
};
}
#endif //TASK03_196_TATARINOV_23_PRODUCER_H
//Producer.cpp
#include <iostream>
#include <thread>
#include "Producer.h"
namespace p_c_model{
Producer::Producer(const std::string& path){
fin.open(path);
}
Producer::~Producer() {
fin.close();
}
void Producer::run() {
std::string unit;
unsigned int price;
while(!fin.eof()){
fin >> unit >> price;
units.add(unit);
prices.add(price);
{
std::unique_lock<std::mutex> locker(mu);
std::cout << "Unit \"" << unit << "\" of price " << price <<
"is taken out of the warehouse\n";
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
}
//Consumer.h
#ifndef TASK03_196_TATARINOV_23_CONSUMER_H
#define TASK03_196_TATARINOV_23_CONSUMER_H
#include <fstream>
#include "Buffer.h"
#include "Producer.h"
namespace p_c_model{
class Producer;
template<class T>
class Consumer{
private:
Buffer<T>& objects;
std::ofstream fout;
std::mutex mu;
unsigned long long overall_price;
public:
explicit Consumer(const std::string& path);
~Consumer();
void run();
void get_buffer(Producer& pr);
};
}
#endif //TASK03_196_TATARINOV_23_CONSUMER_H
//Consumer.cpp
#include <iostream>
#include <thread>
#include "Producer.h"
#include "Consumer.h"
namespace p_c_model{
template<class T>
Consumer<T>::Consumer(const std::string& path) : overall_price(0){
fout.open(path);
}
template<class T>
Consumer<T>::~Consumer() {
fout.close();
std::cout << "Overall price is " << overall_price;
fout << "Overall price is " << overall_price;
}
template<class T>
void Consumer<T>::run() {
if(typeid(T) == typeid(std::string)) {
while (!objects.empty()) {
T unit = objects.remove();
fout << unit;
{
std::unique_lock<std::mutex> locker(mu);
std::cout << "Unit \"" << unit << "\" is entrained in the truck\n";
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
} else if (typeid(T) == typeid(unsigned int)){
while (!objects.empty()) {
T unit = objects.remove();
fout << unit;
overall_price += *reinterpret_cast<unsigned long long *>(&unit);
{
std::unique_lock<std::mutex> locker(mu);
std::cout << "+" << unit << " in price list\n";
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
}
template<class T>
void Consumer<T>::get_buffer(Producer &pr) {
if(typeid(T) == typeid(std::string)){
objects = pr.units;
} else if (typeid(T) == typeid(unsigned int)){
objects = pr.prices;
}
}
}