在收到关于登录不同线程的上一个问题的答案后,我目前处于以下代码段(请注意:此处的并发队列来自ppl,但任何其他的并发队列都应该起作用):
class concurrentFuncQueue
{
private:
typedef std::function<void()> LambdaFunction;
mutable concurrency::concurrent_queue<LambdaFunction> functionQueue;
mutable std::atomic<bool> endcond;
LambdaFunction function;
std::thread thd;
public:
concurrentFuncQueue() : endcond(false), thd([=]{
while (endcond != true)
{
if (functionQueue.try_pop( function ))
{
function(); //note: I am popping a function and adding () to execute it
}
}
}){}
~concurrentFuncQueue() { functionQueue.push([=]{ endcond = true; }); thd.join(); }
void pushFunction(LambdaFunction function) const { functionQueue.push(function); }
};
基本上,我推送的功能是依次在其他线程上运行的(例如,日志记录功能),以避免主线程上的性能问题。
当前的用法如下:
static concurrentFuncQueue Logger;
vector<char> outstring(256);
Logger.pushFunction([=]{ OutputDebugString(debugString.c_str()) });
到目前为止很好。我可以将功能推送到并发队列,该并发队列将在一个单独的线程上按顺序运行我的功能。
我还需要拥有一件事,但目前还不需要返回值,以便ex(伪代码):
int x = y = 3;
auto intReturn = Logger.pushFunction([=]()->int { return x * y; });
会将x * y推送到并发队列,并在该函数的弹出和完成之后(在另一个线程上)将计算出的值返回给调用者线程。
(我知道在返回被推送的函数之前,我将阻塞调用者线程。这正是我想要的)
我感觉到我可能不得不按照std::promise的方式使用某些东西,但是可悲的是,由于我目前对它们的理解不高,我无法制定一些可编码的东西。
有任何想法吗?也欢迎对上面的C++代码和任何其他注释进行思考(如果您认为另一种实现更合适或解决了问题,请完全忽略该代码)。
最佳答案
您应该能够按照以下方式使用某些东西:
template<typename Foo>
std::future<typename std::result_of<Foo()>::type> pushFunction(Foo&& f) {
using result_type = typename std::result_of<Foo()>::type; // change to typedef if using is not supported
std::packaged_task<result_type()> t(f);
auto ret_fut = t.get_future();
functionQueue.push(std::move(t));
return ret_fut;
}
为此,您需要将
LambdaFunction
设置为类型擦除的函数处理程序。