重要更新
注意:由于此问题专门与计时器有关,因此请务必注意gcc中存在一个错误,即如果您使用std::condition_variable::wait_for(或wait_util),即使您将std::传递给它,它也会使用系统时钟。 chrono::steady_clock时间点。这意味着计时器不是单调的-即如果您将系统时间向前更改一天,那么您的计时器可能不会在一天之内触发+您的超时-如果您向后更改时间,则计时器可能会立即触发。
另请:condition_variable workaround for wait_until with system time change
此错误的修复已进入gcc v10 +
END
我有以下代码(手工复制):

// Simple stop watch class basically takes "now" as the start time and
// returns the diff when asked for.
class stop_watch {...}

// global var
std::thread timer_thread;

void start_timer(int timeout_ms)
{
    timer_thread = std::thread([timeout_ms, this](){
        stop_watch sw;
        while (sw.get_elapsed_time() < timeout_ms)
        {
            // Here is the sleep to stop from hammering a CPU
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }

        // Do timeout things here...
        std::cout << "timed out!" << std::endl;
    })
}
我不想对所写类的细节感到困惑,所以这是一个非常精简的版本。完整类调用函数回调,并具有取消计时器等的变量。
我只想关注“睡眠”部分。我可以不睡觉而实现这样的事情吗,或者有更好的方法吗? -还是睡得很好? -我认为睡眠通常是不良设计的标志(我已经读过几个地方了)...但是我想不出一种没有定时器的方法来实现定时器:(
附加说明:计时器应具有能够随时停止/唤醒的要求。只是为了清楚起见才添加它,因为它似乎会影响采用哪种解决方案。在我的原始代码(不是此代码段)中,我使用了可以脱离循环的原子 bool 标志。

最佳答案

C++ 11为我们提供了std::condition_variable。在计时器中,您可以等待直到满足条件:

// Somewhere else, e.g. in a header:
std::mutex mutex;
bool condition_to_be_met{false};
std::condition_variable cv;

// In your timer:
// ...
std::unique_lock<std::mutex> lock{mutex};
if(!cv.wait_for(lock, std::chrono::milliseconds{timeout_ms}, [this]{return condition_to_be_met;}))
std::cout << "timed out!" << std::endl;

您可以在此处找到更多信息:https://en.cppreference.com/w/cpp/thread/condition_variable

要发出已满足条件的信号,请在另一个线程中执行此操作:
{
    std::lock_guard<std::mutex> lock{mutex}; // Same instance as above!
    condition_to_be_met = true;
}
cv.notify_one();

关于c++ - 您可以仅使用标准c++/c++ 11来实现没有 “sleep”的计时器吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51817018/

10-14 09:55