I want learn how to retrieve the return value of a function using a packaged_task.
In the code below I create a thread that runs my function DoTask. I then bind that function to packaged_task and get it to wait while I bind it to a packaged_task myTask. I extract myTask’s future object. Now I unblock the condition variable on DoTask (notify_one) to let it run to completion. I do a get() on myTask’s future to retrieve the value of the return bool in DoTask.
But instead of waiting for DoTask to return, DoTask enters code that does an “INVOKE a function object” and get() never gets executed.
What is keeping DoTask from setting the future I expected it to and instead invokes a function object?
#include "stdafx.h"
#include <future>
#include <memory>
#include <thread>
#include <condition_variable>
#include <mutex>
std::condition_variable notifyCondVar;
std::mutex mu;
bool DoTask()
{
{
std::unique_lock< std::mutex > locker( mu );
notifyCondVar.wait( locker );
}
return true;
}
int main()
{
std::thread packageTaskThread( DoTask );
std::packaged_task< bool() > myTask( std::bind( DoTask ) );
std::future< bool > taskFuture = myTask.get_future();
notifyCondVar.notify_one();
bool okay = taskFuture.get();
packageTaskThread.join();
return 0;
}
You have a thread running DoTask
, and a packaged_task instructed to run DoTask
. You never actually executed the task, so the following two things are wrong:
Perhaps you meant to move-construct the thread from the packaged task, instead:
#include <future>
#include <memory>
#include <thread>
#include <condition_variable>
#include <mutex>
std::condition_variable notifyCondVar;
std::mutex mu;
bool DoTask()
{
std::unique_lock<std::mutex> locker(mu);
notifyCondVar.wait(locker);
return true;
}
int main()
{
std::packaged_task<bool()> myTask([]() { return DoTask(); });
std::future<bool> taskFuture = myTask.get_future();
std::thread packageTaskThread(std::move(myTask));
notifyCondVar.notify_one();
bool okay = taskFuture.get();
packageTaskThread.join();
}
You can see usage examples for std::packaged_task
in this documentation.
(BTW your extra scope block in DoTask
is entirely redundant.)