Reputation: 7342
Hi I don't know how to write a proper bind to queue and execute a lambda expression passed to the method OCRQueue::enqueue()
// the task queue
std::queue< std::function<void(OCRK*)> > tasks;
// add new work item to the pool
template<class F>
auto OCRQueue::enqueue(F&& f)
-> std::future<typename std::result_of<F(OCRK*)>::type>
{
using return_type = typename std::result_of<F(OCRK*)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >
(
// how to initialize this task so that it can be called
// task(OCRK*) passing the parameter to f(OCRK*)
std::bind
(
std::forward<F>(f)
)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if (stop)
throw std::runtime_error("enqueue on stopped thread_pool");
// this fails because task does not accept parameters
tasks.emplace([task](OCRK* ocr){ task(ocr); });
}
condition.notify_one();
return res;
}
Currently this fails to compile on "auto task =" because f expects a parameter of type OCRK* with:
Error 6 error C2064: term does not evaluate to a function taking 0 arguments C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap 58 1 Skilja.PR.API
On: 1> d:\sourcecode\skilja\alpr\alpr\skilja.pr.api.native\OCRQueue.h(51) : see reference to function template instantiation 'std::shared_ptr> std::make_shared,std::_Bind &,>>(std::_Bind &,> &&)' being compiled
The expected usage is like this:
OCRQueue ocrPool(std::thread::hardware_concurrency());
auto work = [](OCRK* ocr)
{
return ocr->DoSomething();
};
future<DoSomethingResult> result = ocrPool.enqueue(work);
The OCRK* will be passed to the enqueued function when dequeued and executed in another thread.
Upvotes: 0
Views: 762
Reputation: 171303
To create a callable object that accepts a single argument you need to tell bind
to use a placeholder for the argument:
std::bind( std::forward<F>(f), std::placeholders::_1 )
This tells bind
to leave an unbound argument, which must be supplied when you call the function object.
But I don't understand why you are using bind
at all, you're not binding anything and f
is already a callable object that accepts a single argument, why don't you just pass it to the packaged_task
constructor?
There is another problem, which is that you say you want a task that accepts a single argument, but you have declared packaged_task<return_type()>
which is a task that takes no arguments. I think you want:
auto task = std::make_shared< std::packaged_task<return_type(OCRK*)> >(std::forward<F>(f));
Also:
tasks.emplace([task](OCRK* ocr){ task(ocr); });
that will still fail because task
is a shared_ptr
, so it is not callable. It should be:
tasks.emplace([task](OCRK* ocr){ (*task)(ocr); });
Upvotes: 2