名稱空間
變體
操作

std::condition_variable::wait_until

來自 cppreference.com
 
 
併發支援庫
執行緒
(C++11)
(C++20)
this_thread 名稱空間
(C++11)
(C++11)
(C++11)
協同取消
互斥
(C++11)
通用鎖管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
條件變數
(C++11)
訊號量
門閂和屏障
(C++20)
(C++20)
期值
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
危險指標
原子型別
(C++11)
(C++20)
原子型別的初始化
(C++11)(C++20 中已棄用)
(C++11)(C++20 中已棄用)
記憶體排序
(C++11)(C++26 中已棄用)
原子操作的自由函式
原子標誌的自由函式
 
 
template< class Clock, class Duration >

std::cv_status
    wait_until( std::unique_lock<std::mutex>& lock,

                const std::chrono::time_point<Clock, Duration>& abs_time );
(1) (C++11 起)
template< class Clock, class Duration, class Predicate >

bool wait_until( std::unique_lock<std::mutex>& lock,
                 const std::chrono::time_point<Clock, Duration>& abs_time,

                 Predicate pred );
(2) (C++11 起)

wait_until 導致當前執行緒阻塞,直到條件變數被通知、達到給定的時間點或發生虛假喚醒。可以可選地提供 pred 來檢測虛假喚醒。

1) 原子性地呼叫 lock.unlock() 並在 *this 上阻塞。
當執行 notify_all()notify_one(),或達到 abs_time 時,執行緒將被解除阻塞。它也可能被虛假地解除阻塞。
當解除阻塞時,呼叫 lock.lock()(可能會在該鎖上阻塞),然後返回。
2) 等價於 while (!pred())
    if (wait_until(lock, abs_time) == std::cv_status::timeout)
        return pred();
return true;
此過載可用於在等待特定條件變為真時忽略虛假喚醒。

wait_until 返回後,lock.owns_lock()true,並且 lock.mutex() 被呼叫執行緒鎖定。如果這些後置條件無法滿足[1],則呼叫 std::terminate

如果滿足以下任何條件,則行為是未定義的:

  • lock.owns_lock()false
  • lock.mutex() 未被呼叫執行緒鎖定。
  • 如果其他執行緒也在 *this 上等待,則 lock.mutex() 不同於那些執行緒在 *this 上呼叫的等待函式(waitwait_forwait_until)解鎖的互斥量。
  1. 這可能發生於對互斥體重新加鎖時丟擲異常。

目錄

[編輯] 引數

lock - 一個必須被呼叫執行緒鎖定的鎖
abs_time - 等待過期的時刻
pred - 用於檢查是否可以完成等待的謂詞
型別要求
-
Predicate 必須滿足函式物件 (FunctionObject) 的要求。
-
pred() 必須是有效的表示式,其型別和值類別必須滿足 BooleanTestable 要求。

[編輯] 返回值

1) 如果達到 abs_time,則返回 std::cv_status::timeout,否則返回 std::cv_status::no_timeout
2) 在返回給呼叫者之前,pred() 的最新結果。

[編輯] 異常

1) 與超時相關的異常。
2) 與超時相關的異常,以及由 pred 丟擲的任何異常。

[編輯] 注意

標準建議使用與 abs_time 繫結的時鐘來測量時間;該時鐘不要求是單調時鐘。如果時鐘不連續調整,則無法保證此函式的行為,但現有實現會將 abs_timeClock 轉換為 std::chrono::system_clock 並委託給 POSIX pthread_cond_timedwait,以便等待遵守系統時鐘的調整,但不遵守使用者提供的 Clock。無論如何,由於排程或資源爭用延遲,該函式也可能等待超過 abs_time 之後才達到。

即使使用的時鐘是 std::chrono::steady_clock 或其他單調時鐘,系統時鐘調整也可能導致虛假喚醒。

notify_one()/notify_all()wait()/wait_for()/wait_until() 的三個原子部分(解鎖+等待、喚醒和鎖定)的效果發生在單個總序中,可以看作原子變數的修改順序:該順序特定於此單個條件變數。這使得 notify_one() 不可能(例如)延遲並解除阻塞在呼叫 notify_one() 之後才開始等待的執行緒。

[編輯] 示例

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
 
std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;
 
void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{ return i == 1; });
    std::cerr << "...finished waiting. i == 1\n";
}
 
void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m);
        std::cerr << "Notifying...\n";
    }
    cv.notify_all();
 
    std::this_thread::sleep_for(std::chrono::seconds(1));
 
    {
        std::lock_guard<std::mutex> lk(cv_m);
        i = 1;
        std::cerr << "Notifying again...\n";
    }
    cv.notify_all();
}
 
int main()
{
    std::thread t1(waits), t2(waits), t3(waits), t4(signals);
    t1.join(); 
    t2.join(); 
    t3.join();
    t4.join();
}

可能的輸出

Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 2093 C++11 規範中缺少與超時相關的異常 提及這些異常
LWG 2114
(P2167R3)
C++11 可轉換為 bool 對於反映實現的期望來說太弱了 要求已加強
LWG 2135 C++11 如果 lock.lock() 丟擲異常,則行為不明確 在這種情況下呼叫 std::terminate

[編輯] 參閱

阻塞當前執行緒直到條件變數被喚醒
(公共成員函式) [編輯]
阻塞當前執行緒,直到條件變數被喚醒或達到指定的超時時長。
(公共成員函式) [編輯]