我必须用C ++编写一个多生产者 - 消费者系统,但是我试图将模型的每个部分(具有正确缓冲区的线程)放在一起。该模型的基本功能是:我有一个执行函数的初始线程。返回的结果需要放在未确定数量的缓冲区中,因为函数进程的每个元素都不同,需要在单个线程中处理。然后,在存储在缓冲区中的数据中,另一个n
线程需要获取此缓冲区的数据以执行另一个函数,并且需要将此返回值再次放入某些缓冲区中。
目前我已经创建了这个缓冲区结构:
template <typename T>
class buffer {
public:
atomic_buffer(int n);
int bufSize() const noexcept;
bool bufEmpty() const noexcept;
bool full() const noexcept;
~atomic_buffer() = default;
void put(const T & x, bool last) noexcept;
std::pair<bool,T> get() noexcept;
private:
int next_pos(int p) const noexcept;
private:
struct item {
bool last;
T value;
};
const int size_;
std::unique_ptr<item[]> buf_;
alignas(64) std::atomic<int> nextRd_ {0};
alignas(64) std::atomic<int> nextWrt_ {0};
};
我还创建了一个vector
结构,它存储一个集合un缓冲区,以满足不确定数量的线程的必要性。
std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;
for(int i=0; i<n; i++){
v1.push_back(std::unique_ptr<locked_buffer<std::pair<int,std::vector<std::vector<unsigned char>>>>> (new locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>(aux)));
}
编辑:
答案 0 :(得分:2)
在不了解更多上下文的情况下,这看起来像是标准线程池的应用程序。您有不同的任务排队到同步队列(如您所在的buffer
类)。线程池的每个工作线程轮询此队列并每次处理一个任务(例如,通过执行run()
方法)。他们将结果写回另一个同步队列。
每个工作线程都有一个自己的线程本地输入和输出缓冲区对。他们不需要同步,因为只能从所有者线程本身访问它们。
编辑:实际上,我认为这可以简化很多:只需使用线程池和一个同步队列。工作线程可以将新任务直接排入队列。图中的每个线程都对应一种类型的任务,并实现一个通用的Task
接口。
你不需要多个缓冲区。您可以使用多态并将所有内容放在一个缓冲区中。
编辑2 - 线程池说明:
线程池只是一个概念。忘记池方面,使用固定数量的线程。主要思想是:有N个线程可以处理任何类型的任务,而不是让几个线程具有特定的功能。其中N是CPU的核心数。
你可以改变这个
进入
工作线程执行类似以下操作。请注意,这是简化的,但您应该明白这一点。
void Thread::run(buffer<Task*>& queue) {
while(true) {
Task* task = queue.get();
if(task)
task->execute();
while(queue.isEmpty())
waitUntilQueueHasElement();
}
}
您的任务实现了一个通用接口,因此您可以将Task*
指针放入一个队列中:
struct Task {
virtual void execute() = 0;
}
struct Task1 : public Task {
virtual void execute() override {
A();
B1();
C();
}
}
...
另外,帮自己一个忙,并使用typedef;)
`std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;`
变为
typedef std::vector<std::vector<unsigned char>> vector2D_uchar;
typedef std::pair<int, vector2D_uchar> int_vec_pair;
typedef std::unique_ptr<locked_buffer<int_vec_pair>> locked_buffer_ptr;
std::vector<locked_buffer_ptr> v1;