概述
我正在用C++实现一个生产者-消费者模型。我有多个消费者,每个消费者都有自己的线程和队列。为了便于访问,我想要一个表单<ID、消费者实例>,这样我就可以在向consumers线程推送数据时通过查找简单地获取它。当试图访问存储实例方法时,编译器会抛出一个错误。
密码
使用者类启动一个带有附加FIFO队列的线程,并等待项目被推入(此处提供队列头:
https://github.com/cameron314/readerwriterqueue/blob/master/readerwriterqueue.h
)
// consumer.h
#include <functional>
#include <thread>
#include "readerwriterqueue.h"
// TYPE HAS TO BE A POINTER
template<typename T>
class Consumer
{
public:
Consumer(int id, std::function<void(int, T&)> func) :
m_id(id), m_func(func) {}
~Consumer(){
m_running = false;
this->pushBack(nullptr);
m_thread.join();
}
// satisfy rule of three; disallow copying as we manage a thread
Consumer(const Consumer&) = delete;
Consumer& operator=(const Consumer&) = delete;
void pushBack(const T& t){
m_BufferQueue.enqueue(t);
}
private:
void work() {
m_running = true;
while(m_running || m_BufferQueue.peek())
{
T t;
m_BufferQueue.wait_dequeue(t);
if (t == nullptr)
break;
m_func(m_id, t);
}
}
int m_id;
std::function<void(int, T&)> m_func;
moodycamel::BlockingReaderWriterQueue<T> m_BufferQueue{64};
std::thread m_thread{&Consumer::work, this};
std::atomic_bool m_running;
};
我想创建这个类的多个实例,并将它们放在一个无序的映射中,这样我就可以在必要时推入它们的队列。据我所知,模板可以帮助我避免在创建对象并将其直接放置在映射中时编写移动构造函数/赋值运算符。
// main_player.cpp
#include <iostream>
#include <unordered_map>
#include "consumer.h"
void func(int id, int* val)
{
std::cout << "Thread " << id << " received value " << *val << "\n";
}
int main(int argc, char** argv) {
std::unordered_map<int, Consumer<int*>> consumers;
consumers.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple(0, func));
// push into queues here and let the threads do the work
for(int i = 0; i < 5; i++)
consumers[0].pushBack(&i)
return 0;
}
编译器在将返回推送到队列中时出现问题。从错误日志中,我可以推断他似乎确实构建了另一个实例,但失败了。有人能帮我吗?
错误日志
In file included from /usr/include/c++/7/functional:54:0,
from ../consumer.h:4,
from ../main_player.cpp:31:
/usr/include/c++/7/tuple: In instantiation of âstd::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = Consumer<int*>]â:
/usr/include/c++/7/tuple:1641:63: required from âstd::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = Consumer<int*>]â
/usr/include/c++/7/ext/new_allocator.h:136:4: required from âvoid __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, Consumer<int*> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::pair<const int, Consumer<int*> >]â
/usr/include/c++/7/bits/alloc_traits.h:475:4: required from âstatic void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, Consumer<int*> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::pair<const int, Consumer<int*> >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::pair<const int, Consumer<int*> > >]â
/usr/include/c++/7/bits/hashtable_policy.h:2066:37: required from âstd::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, Consumer<int*> >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const int, Consumer<int*> >, false>]â
/usr/include/c++/7/bits/hashtable_policy.h:750:8: required from âstd::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type& std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::operator[](std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type&&) [with _Key = int; _Pair = std::pair<const int, Consumer<int*> >; _Alloc = std::allocator<std::pair<const int, Consumer<int*> > >; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type = Consumer<int*>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = int]â
/usr/include/c++/7/bits/unordered_map.h:977:20: required from âstd::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type&&) [with _Key = int; _Tp = Consumer<int*>; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, Consumer<int*> > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = Consumer<int*>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = int]â
../main_player.cpp:48:20: required from here
/usr/include/c++/7/tuple:1652:70: error: no matching function for call to âConsumer<int*>::Consumer()â
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from ../main_player.cpp:31:0:
../consumer.h:13:5: note: candidate: Consumer<T>::Consumer(int, std::function<void(int, T&)>) [with T = int*]
Consumer(int id, std::function<void(int, T&)> func) :
^~~~~~~~
../consumer.h:13:5: note: candidate expects 2 arguments, 0 provided
make: *** [main_player.o] Error 1
subdir.mk:66: recipe for target 'main_player.o' failed
"make -j20 all" terminated with exit code 2. Build might be incomplete.
18:01:03 Build Failed. 3 errors, 0 warnings. (took 739ms)