我正在尝试执行创建packaged_task队列的程序,并尝试在单独的线程中执行packaged_tasks。我收到以下错误
错误C2664'std :: function <_Ret(void)> :: function(std :: function <_Ret(void)> &&)':无法将参数1从'std :: _ Binder转换'到'std :: nullptr_t'
我的代码如下所示。关于此错误发生原因,是否可以有任何指南?
/*
****************************************************************************************************
The Header File
****************************************************************************************************
*/
class CommandChannel {
private:
std::thread commChannelThread;
std::mutex commChannelmu;
std::condition_variable commChannelcv;
struct taskRequest
{};
struct taskResponse
{};
/* Creates a queue of packaged tasks that accepts one iu */
std::deque< std::packaged_task<int()>> comm_ch_task_queue;
void threadHandler(void);
protected:
int p_impl_theAdd(int a, int b);
int p_impl_theMul(int a, int b);
int p_impl_theDiv(int a, int b);
public:
/*Constructor and the Destructor*/
CommandChannel();
~CommandChannel();
/*The public functions */
int theAdd(int a, int b);
int theMul(int a, int b);
int theDiv(int a, int b);
};
/*
****************************************************************************************************
The Implementation File
****************************************************************************************************
*/
/* Implementation Functions */
int CommandChannel::p_impl_theAdd(int a, int b)
{
return a+b;
}
int CommandChannel::p_impl_theMul(int a, int b)
{
return a*b;
}
int CommandChannel::p_impl_theDiv(int a, int b)
{
return a / b;
}
/* COnstructors and Destructors */
CommandChannel::CommandChannel()
{
/*Creating a new thread that runs the threadHandler function*/
commChannelThread = std::thread(&CommandChannel::threadHandler, this);
}
CommandChannel::~CommandChannel()
{
if (commChannelThread.joinable()) {
commChannelThread.join();
std::cout << "Command Channel Thread Joined " << std::endl;
}
else
std::cout << "Problem in joining the Command Channel Thread" << std ::endl;
}
/* User Public Functions */
int CommandChannel::theAdd(int a, int b)
{
/* Creating the packaged task with the the implementation pointer */
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theAdd, a, b));
/* Pushing the task in the queue */
{
std::lock_guard<std::mutex> locker(commChannelmu);
comm_ch_task_queue.push_back(t);
commChannelcv.notify_one();
}
/* creating the placeholder for the return value */
std::future<int> fu = t.get_future();
/* getting the value from the future */
return fu.get();
}
int CommandChannel::theMul(int a, int b)
{
/* Create the packaged task with the pimpl */
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theMul, a, b));
/* Pushing the task in the queue */
{
std::lock_guard<std::mutex> locker(commChannelmu);
comm_ch_task_queue.push_back(t);
commChannelcv.notify_one();
}
/* Creating the placeholder for the return value */
std::future<int> fu = t.get_future();
/*getting the value from the future*/
return fu.get();
}
int CommandChannel::theDiv(int a, int b)
{
/* Create the packaged tasks with the pimpl */
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theDiv, a, b));
/*Pushing the task in the queue thorigh the mutex locks*/
{
std::lock_guard<std::mutex> locker(commChannelmu);
comm_ch_task_queue.push_back(t);
commChannelcv.notify_one();
}
/* Creating the placeholder for the return value */
std::future<int> fu = t.get_future();
/*getting the value from the future*/
return fu.get();
}
/*
Thread Handler
Pops the elemetns from the queue and then executes them
the value goes to the called function through future references
*/
void CommandChannel::threadHandler()
{
std::packaged_task<int()> t;
{
std::unique_lock<std::mutex> locker(commChannelmu);
commChannelcv.wait(locker);
t = std::move(comm_ch_task_queue.front());
comm_ch_task_queue.pop_front();
}
t();
}
/*
****************************************************************************************************
Main
****************************************************************************************************
*/
int main()
{
CommandChannel api;
api.theAdd(2, 4);
api.theDiv(6, 3);
api.theMul(5, 7);
return 0;
}
答案 0 :(得分:0)
您的代码中有两个错误。首先,您使用的活页夹不正确。在绑定成员函数时,第一个参数应具有指向类的指针,在您的情况下为this
。这是固定代码的一个示例:
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theDiv, this, a, b));
但是,使用lambdas通常比活页夹更加直观和语法友好。这是用lambda表达的相同想法:
std::packaged_task<int()> t([this, a, b]() {return p_impl_theDiv(a, b);});
此外,一旦固定所有位置,您将遇到另一个问题-您正在复制packaged_task
对象,同时将它们推入队列。这些对象不可复制,您必须移动。同样,这是此修复程序的一个实例:
comm_ch_task_queue.push_back(std::move(t));
此代码可能还有其他问题,我只修复了编译错误。
答案 1 :(得分:0)
您正在绑定类的非静态成员函数,
所以您需要指定对象
成员函数被调用。 this
丢失
在bind
的所有调用中:
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theDiv, this, a, b));
对theMul
和theAdd
做同样的事情。
第二个问题,packaged_task
对象无法复制,
如果要将此对象作为参数传递
push_back
,您必须投射packaged_task
对象
到右值引用,则packaged_task
将被移动
进入向量。
comm_ch_task_queue.push_back(std::move(t));
以上所有都是为了消除编译期间的错误。
1)
由于packaged_task
以theDiv
方法移动,
在执行移动操作后,您无法调用该对象的任何成员。
按下packaged_task
后,您应该退出theDiv
函数。
void CommandChannel::theDiv(int a, int b)
{
/* Create the packaged tasks with the pimpl */
std::packaged_task<int()> t(std::bind(&CommandChannel::p_impl_theDiv, this, a, b));
/*Pushing the task in the queue thorigh the mutex locks*/
{
std::lock_guard<std::mutex> locker(commChannelmu);
comm_ch_task_queue.push_back(std::move(t));
commChannelcv.notify_one();
}
// access to t is forbidden
}
使用theAdd
和theMul
方法做同样的事情。
2)您的线程函数仅从队列执行一项任务。 我认为那里缺少一些循环。您要将所有传入任务执行到队列中(注释中的详细信息):
void CommandChannel::threadHandler()
{
std::packaged_task<int()> t;
while (true) // inifite loop to process incoming tasks
{
std::unique_lock<std::mutex> locker(commChannelmu);
commChannelcv.wait(locker,[this](){ return comm_ch_task_queue.size();});
// wait returns if there is some task to be performed
t = std::move(comm_ch_task_queue.front());
comm_ch_task_queue.pop_front();
std::future<int> f = t.get_future();
t(); // perform task
std::cout << f.get() << std::endl; // print value
}
}