public member function
<mutex>

std::call_once

template <class Fn, class... Args>  void call_once (once_flag& flag, Fn&& fn, Args&&... args);
只調用一次函式
呼叫 fn 並將 args 作為引數傳遞,除非另一個執行緒已經使用相同的 flag 執行(或正在執行)一次 call_once 呼叫。

如果另一個執行緒正在與同一 flag 主動執行 call_once 呼叫,則會發生被動執行被動執行 不呼叫 fn,但直到主動執行本身返回並且所有可見的副作用在此刻同步到具有相同 flag 的所有併發呼叫為止,才返回。

如果一次主動執行透過丟擲異常(該異常會傳播到其呼叫執行緒)而結束,並且存在被動執行,則會從這些被動執行中選擇一個,並將其呼叫為新的主動執行

請注意,一旦主動執行返回,所有當前的被動執行以及未來(具有相同 flag)對 call_once 的呼叫都將返回,而不會成為主動執行

主動執行使用 fnargslvaluervalue 引用的decay 副本,並忽略 fn 返回的值。

引數

flag
用於跟蹤呼叫狀態的函式物件。
在不同執行緒中使用相同的物件進行呼叫,如果併發呼叫,則只執行一次。
如果 flag 的狀態無效,則函式會丟擲帶有 invalid_argument 錯誤條件的 system_error 異常。
如果 flag 的狀態無效,則該呼叫會導致未定義行為
call_once 是在標頭檔案 <mutex> 中定義的用於作為此函式引數的特定型別。
fn
函式指標、成員指標,或任何可移動構造的函式物件(即,其類定義了 operator() 的物件,包括閉包function 物件)。
返回值(如果有)將被忽略。
args...
傳遞給 fn 的引數。它們的型別必須是可移動構造的。
如果 fn成員指標,則第一個引數應為定義了該成員的物件(或其引用或指標)。

返回值



示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// call_once example
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <chrono>         // std::chrono::milliseconds
#include <mutex>          // std::call_once, std::once_flag

int winner;
void set_winner (int x) { winner = x; }
std::once_flag winner_flag;

void wait_1000ms (int id) {
  // count to 1000, waiting 1ms between increments:
  for (int i=0; i<1000; ++i)
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  // claim to be the winner (only the first such call is executed):
  std::call_once (winner_flag,set_winner,id);
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(wait_1000ms,i+1);

  std::cout << "waiting for the first among 10 threads to count 1000 ms...\n";

  for (auto& th : threads) th.join();
  std::cout << "winner thread: " << winner << '\n';

  return 0;
}

可能的輸出(獲勝者可能不同)

waiting for the first among 10 threads to count 1000 ms...
winner thread: 2


資料競爭

該函式修改 flag,並訪問 fnargs 以建立其 lvaluervalue 引用的decay 副本

異常安全

如果函式本身失敗,它會丟擲 system_error 異常,並使所有物件處於有效狀態(基本保證)。
否則,主動執行提供與對引數執行的操作相同的保證級別。

另見