给定std :: chrono :: duration :: max后,std :: condition_variable :: wait_for立即退出

Tim*_*ynn 5 condition-variable mingw-w64 c++11 c++-chrono

我有一个std::queue使用C ++ 11语义来允许并发访问的包装器。该std::queue保护带std::mutex。将项目推送到队列时,std::condition_variable会通过调用通知a notify_one

有两种从队列中弹出项目的方法。一种方法将无限期地阻塞,直到使用将该项目推送到队列中为止std::condition_variable::wait()。第二个将阻塞std::chrono::duration单位使用的时间std::condition_variable::wait_for()

template <typename T> template <typename Rep, typename Period>
void ConcurrentQueue<T>::Pop(T &item, std::chrono::duration<Rep, Period> waitTime)
{
    std::cv_status cvStatus = std::cv_status::no_timeout;
    std::unique_lock<std::mutex> lock(m_queueMutex);

    while (m_queue.empty() && (cvStatus == std::cv_status::no_timeout))
    {
        cvStatus = m_pushCondition.wait_for(lock, waitTime);
    }

    if (cvStatus == std::cv_status::no_timeout)
    {
        item = std::move(m_queue.front());
        m_queue.pop();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我在空队列中像这样调用此方法时:

ConcurrentQueue<int> intQueue;

int value = 0;
std::chrono::seconds waitTime(12);

intQueue.Pop(value, waitTime);
Run Code Online (Sandbox Code Playgroud)

然后12秒后,对Pop()的调用将退出。但是,如果将waitTime设置为std::chrono::seconds::max(),则对Pop()的调用将立即退出。毫秒:: max()和小时数:: max()相同。但是,days :: max()可以正常工作(不会立即退出)。

是什么导致seconds :: max()立即退出?

这是用mingw64编译的:

g++ --version

g++ (rev5, Built by MinGW-W64 project) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 4

首先,定时等待可能应该是 a wait_until(lock, std::chrono::steady_clock::now() + waitTime);,而不是wait_for因为循环现在将简单地重复等待多次,直到最终条件 ( m_queue.empty()) 变为 true 。重复也可能是由虚假唤醒引起的。

\n\n

使用谓词等待方法修复部分代码:

\n\n
template <typename Rep, typename Period>\nbool pop(std::chrono::duration<Rep, Period> waitTime, int& popped)\n{\n    std::unique_lock<std::mutex> lock(m_queueMutex);\n\n    if (m_pushCondition.wait_for(lock, waitTime, [] { return !m_queue.empty(); }))\n    {\n        popped = m_queue.back();\n        m_queue.pop_back();\n        return true;\n    } else\n    {\n        return false;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的实施中至少seconds::max()产生了0x7fffffffffffffff

\n\n

\xc2\xa730.5.1 ad 26 状态:

\n\n
\n

效果:仿佛

\n\n
 return wait_until(lock, chrono::steady_clock::now() + rel_time);\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

正在做

\n\n
auto time = steady_clock::now() + seconds::max();\nstd::cout << std::dec << duration_cast<seconds>(time.time_since_epoch()).count() << "\\n";\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我的系统上,打印

\n\n
265521\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用date --date=\'@265521\' --rfc-822告诉我那是Sun, 04 Jan 1970 02:45:21 +0100

\n\n

GCC 和 Clang 存在环绕错误,请参见下文

\n\n
\n\n

测试员

\n\n

Live On Coliru

\n\n
#include <thread>\n#include <condition_variable>\n#include <iostream>\n#include <deque>\n#include <chrono>\n#include <iomanip>\n\nstd::mutex m_queueMutex;\nstd::condition_variable m_pushCondition;\n\nstd::deque<int> m_queue;\n\ntemplate <typename Rep, typename Period>\nbool pop(std::chrono::duration<Rep, Period> waitTime, int& popped)\n{\n    std::unique_lock<std::mutex> lock(m_queueMutex);\n\n    if (m_pushCondition.wait_for(lock, waitTime, [] { return !m_queue.empty(); }))\n    {\n        popped = m_queue.back();\n        m_queue.pop_back();\n        return true;\n    } else\n    {\n        return false;\n    }\n}\n\nint main()\n{\n    int data;\n    using namespace std::chrono;\n\n    pop(seconds(2)    , data);\n\n    std::cout << std::hex << std::showbase << seconds::max().count() << "\\n";\n    auto time = steady_clock::now() + seconds::max();\n    std::cout << std::dec << duration_cast<seconds>(time.time_since_epoch()).count() << "\\n";\n    pop(seconds::max(), data);\n}\n
Run Code Online (Sandbox Code Playgroud)\n