我该如何等待多个事物?

3
我正在使用C++11和STL线程编写一个线程安全队列。目前WaitAndPop方法的代码如下。我希望能够传递一个参数给WaitAndPop,以指示调用线程是否已被要求停止。如果WaitAndPop等待并返回了队列中的元素,则应返回true;如果调用线程正在被停止,则应返回false。
    bool WaitAndPop(T& value, std::condition_variable callingThreadStopRequested)
    {
        std::unique_lock<std::mutex> lock(mutex);
        while( queuedTasks.empty() )
        {
            queuedTasksCondition.wait(lock);
        }

        value = queue.front();
        queue.pop_front();
        return true;
    }

能否编写类似于这样的代码?我习惯使用Win32中的WaitForMultipleObjects,但找不到适用于此情况的替代方法。

谢谢。

我看到了相关问题,但它并没有真正回答我的问题。在Linux上学习线程


1
我的解决方案是使用poll()和使用管道来处理POSIX的WaitForMultipleEvents。然而,我不认为这对你的条件变量有帮助... - trojanfoe
1
我认为这是一种推荐的方式,正如Antony Williams在“使用条件变量实现线程安全队列”的文章中所描述的- http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html。 - SChepurin
在关闭场景下,我可能可以将一些特殊值推送到队列中,告诉WaitAndPop在弹出该值时返回false。而且我可能还能使其跳到队列的前面以更快地终止。 - Scott Langham
是的,我终于明白你的意思了,谢谢。 - didierc
1
我认为你必须在所有你希望线程等待的事物上实现cond变量的共享。这是最简单的方法。否则,您可以回到使用fs对象并使用select/poll,但这是posix,而不是纯C++,因此...我认为在C++中真的没有类似于WaitForMultipleObjects的等效物。 - didierc
显示剩余3条评论
1个回答

9

如果我理解您的问题正确,我可能会这样做:

 bool WaitAndPop(T& value)
 {
    std::unique_lock<std::mutex> lk(mutex);            

    // Wait until the queue won't be empty OR stop is signaled
    condition.wait(lk, [&] ()
    {
        return (stop || !(myQueue.empty()));
    });

    // Stop was signaled, let's return false
    if (stop) { return false; }

    // An item was pushed into the queue, let's pop it and return true
    value = myQueue.front();
    myQueue.pop_front();

    return true;
}

在这里,stop是一个全局变量,就像conditionmyQueue一样(我建议不要使用queue作为变量名,因为它也是标准容器适配器的名称)。控制线程可以将stop设置为true(同时持有mutex的锁),并在condition上调用notifyOne()notifyAll()
这样,当新项目被推入队列中时,会在条件变量上调用notify***(),并且在发出stop信号时也会调用notify***()。这意味着等待在该条件变量上的线程在唤醒后必须检查其被唤醒的原因,并相应地采取行动。

@didierc:确实。让我们看看原帖作者是否会满意 :) - Andy Prowl
1
@AndyProwl 我会和他确认的。 :) - Scott Langham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接