• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    function
    <atomic>

    std::atomic_ref::address

    constexpr T* address() const noexcept;
    

    概要

    参照しているオブジェクトのアドレスを取得する。

    この関数を必要とする状況

    データ構造の要素へのアトミックアクセス

    配列の各要素にアトミックアクセスする際、std::atomicオブジェクトでは以下のように記述する。

    std::array<std::atomic<int>, N> array;
    
    int fetch_add_idx(std::atomic<int>* base, size_t i, int value) {
      return base[i].fetch_add(value);
    }
    

    これをstd::atomic_refで記述する場合、アトミック性をもたせてアクセスするには、この関数を使用して以下のようにする。

    int fetch_add_idx(std::atomic_ref<int> base, size_t i, int value) {
      int* p = base.address();
      return std::atomic_ref{*(p+i)}.fetch_add(value);
    }
    

    • fetch_add[link fetch_add.md

    必要なときにのみアトミックアクセスする

    以下の例では、複数のスレッドが並行にメモリにアクセスし、カウンタをインクリメントすることでアクセス終了を知らせている。最後のスレッドはメモリにアクセスする余分な処理を実行する必要があるが、並行にメモリにアクセスするほかのスレッドがないため、これらのアクセスはアトミックである必要がない:

    void thread(atomic_ref<int>* data, atomic_ref<int> counter, int nthreads) {
      data->fetch_add(42, memory_order_relaxed);
      int* d = data->address();       // dataへの生ポインタを取得
      data->~atomic_ref();            // このスレッドのデータへのatomic_refを破棄する
      int pos = counter.fetch_add(1); // データの破棄が完了したことを伝える
      if (pos != (nthreads - 1))
        return;
    
      // 最後のスレッド: アトミックアクセスする必要がない
      int last_data = *d; // 非アトミックアクセス
      // …
    } 
    

    戻り値

    *thisが参照するオブジェクトをアドレス値を返す

    例外

    投げない

    #include <iostream>
    #include <atomic>
    #include <thread>
    
    void f(std::atomic_ref<int> ar, int i) {
      int* p = ar.address();
      std::atomic_ref{p + i}.fetch_add(1);
    }
    
    int main()
    {
      int ar[3] = {};
    
      std::thread t1{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
      std::thread t2{[&ar]{ f(std::atomic_ref{ar[0]}, 1); }};
    
      t1.join();
      t2.join();
    
      std::cout << ar[1] << std::endl;
    }
    

    出力

    2
    

    バージョン

    言語

    • C++26

    処理系

    参照