• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠,我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數據加載中……

            C++ Atomic

            C++ Atomic

            atomic 是STL(標準庫)中的一個頭文件, 定義了 C++11標準中的一些表示 線程并發控制 時 原子操作 的類與方法. 主要聲明了兩個類模板: std::atomic 和 std::atomic_flag, 另外還聲明了一套C風格的原子類型 與 C兼容的原子操作的函數.

            在多線程并發執行時, 原子操作 是線程不會打斷的執行片段. 一些程序設計更為注重性能和效率, 需要開發 lock-free 的算法與數據結構, 這就需要更為底層的 原子操作 與 原子類型原子類型對象的主要特點就是從不同的線程并發訪問是 良性(well-defined) 行為, 不會導致 競爭危害. 與之相反, 不做適當控制就并發訪問 非原子對象 則會導致 未定義(undefined) 行為.

            內存序模型

            僅靠原子指令實現不了對資源的訪問控制. 這造成的原因是編譯器和cpu實施了重排指令, 導致讀寫順序會發生變化, 只要不存在依賴, 代碼中后面的指令可能會被放在前面, 從而先執行它. cpu這么做是為了盡量塞滿每個時鐘周期, 在單位時間內盡量執行更多的指令, 從而提高吞吐率.

            我們先來看兩個線程代碼:

            // thread 1 // flag初始值為false     a.init();     flag = true;
            // thread 2     if(flag) {         a.bar();     }

            線程2在ready為true的時候會訪問p, 對線程1來說, 如果按照正常的執行順序, 那么p先被初始化, 然后在將ready賦為true. 但對多核的機器而言, 情況可能有所變化:

            • 線程1中的 ready = true 可能會被CPU或編譯器 重排序 到 p.init() 的前面, 從而優先執行 ready = true 這條指令. 在線程2中, p.bar() 中的一些代碼可能被重排到 if(ready) 之前.
            • 即使沒有 重排序, ready和p的值也會獨立地同步到線程2所在核心的cache, 線程2仍然可能在看到ready為true時看到未初始化的p.

            為了解決這個問題, 我們一種解決方法是使用互斥元, 還有一種就是CPU和編譯器提供了memory fence, 讓用戶可以聲明訪存指令的可見性關系, C++11總結為以下memory order

            內存序模型 是討論在 原子操作 附近的 讀寫 操作順序

            // c++11  ~~  c++17
            typedef enum memory_order {
            memory_order_relaxed,
            memory_order_consume,
            memory_order_acquire,
            memory_order_release,
            memory_order_acq_rel,
            memory_order_seq_cst
            } memory_order;
            
            //c++20
            enum class memory_order : /*unspecified*/ {
            relaxed, consume, acquire, release, acq_rel, seq_cst
            };
            inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
            inline constexpr memory_order memory_order_consume = memory_order::consume;
            inline constexpr memory_order memory_order_acquire = memory_order::acquire;
            inline constexpr memory_order memory_order_release = memory_order::release;
            inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
            inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
            
            • memory_order_relaxed: 只保證 原子操作 的 原子性 .

              fencing作用, CPU和編譯器 可以 重排序 指令

            • memory_order_consume: 使用這種 內存序 的  操作在被影響的內存位置上執行consume操作:

              • 當前線程依賴于這個當前 讀取值的 讀寫 操作 不能 重排序 到這條  操作之前;
              • 這個 原子變量 的其他線程的數據依賴變量的 寫入 對當前線程 可見 .
              • 在大多數平臺, 這 只影響 編譯器的行為.

              后面 依賴此 原子變量 的訪存指令 不能 重排序 至此條指令之前

            • memory_order_acquire: 使用這種 內存序 的  操作在被影響的內存位置上執行acquire操作:

              • 當前線程的 讀寫 不能 被 重排序 在這條  操作之前.
              • 其他線程對這個原子變量的所有  操作對當前線程是 可見 的.

              后面 依賴此 原子變量 的訪存指令 不能 重排序 至此條指令之前

            • memory_order_release: 使用這種 內存序 的  操作在被影響的內存位置上執行release操作:

              • 當前線程的 讀寫 不能被 重排序 在這條  操作之后.
              • 當前線程的所有  操作對其他  這個 原子變量 的線程是 可見 的.
              • 導致這個 原子變量 依賴的  操作對于其他 consume 這個 原子變量 的線程是 可見 的.

              前面 依賴此 原子變量 的訪存指令 不能 重排序 到此條指令之后. 當此條指令的結果被同步到其他核的cache中時, 保證前面的指令也已經被同步.

            • memory_order_acq_rel: 使用這種 內存序 的一個 read-modify-write 操作既是 acquire 操作也是 release 操作. 當前線程的 讀寫 不能 被 重排序 在這條操作之前以及之后. 其他線程對這個 原子變量 的 release 對本線程是 可見 的. 本線程的這條操作結果對其他 讀取 該 原子變量 的線程是 可見 的.

              acquare + release

            • memory_order_seq_cst: 使用這種 內存序 的  操作在被影響的內存位置上執行 acquire 操作, 使用這種 內存序 的  操作在被影響的內存位置上執行 release 操作, 使用這種 內存序 的一個 read-modify-write 操作既是 acquire 操作也是 release 操作. 并存在一個全序, 所有線程看到的所有修改是同樣的順序.

              acquare + release + 所有使用 memory_order_seq_cst 的指令有嚴格的全序關系

            有了 memory_order, 我們可以這么改上面的例子:

            // thread 1 // flag初始值為false     a.init();     flag.store(true, std::memory_order_release);  //前面的不能在我后面執行
            // thread 2     if(flag.load(std::memory_order_acquire)) {   //后面的不能在我前面執行         a.bar();     }

            這樣就保證了線程1和線程2的順序性, 比如線程2在看到flag==true時, 能看到線程1 realse之前所有操作. 也就保證了代碼符合我們的預期.

            注意 : memory fence(內存柵欄) 不等于可見性, 即使線程2恰好在線程1在把flag設置為true后讀取了flag也不意味著它能看到true, 因為同步cache是有延時的. memory fence保證的是可見性的順序: "假如我看到了a的最新值, 那么我一定也得看到b的最新值".

            atomic_flag類型

            atomic_flag 是一種簡單的原子布爾類型, 只支持兩種操作: test_and_set 和 clear.

            結合 std::atomic_flag::test_and_set() 和 std::atomic_flag::clear()std::atomic_flag 對象可以當作一個簡單的自旋鎖(spin lock)使用.

            構造函數

            atomic_flag() noexcept = default;           //只有默認構造函數
            atomic_flag (const atomic_flag&T) = delete; //禁用拷貝構造函數
            

            移動構造函數實際上也禁用. 根據C++標準的一般規定, 如果一個類顯式聲明了拷貝構造函數(即使是作為delete), 就不會有缺省的移動構造函數.
            相關的宏:如果在初始化時沒有明確使用宏ATOMIC_FLAG_INIT初始化, 那么新創建的std::atomic_flag 對象的狀態是 未指定的(unspecified), 既沒有被 set 也沒有被 clear ; 如果使用該宏初始化, 該 std::atomic_flag 對象在創建時處于 clear 狀態.

            成員函數

            //返回該std::atomic_flag對象當前狀態,如果當前狀態為false則設置(set) 該對象為true. 該函數是原子的
            bool test_and_set (memory_order sync = memory_order_seq_cst) volatile noexcept;
            bool test_and_set (memory_order sync = memory_order_seq_cst) noexcept;
            //清除std::atomic_flag 對象的標志位, 即設置atomic_flag 的值為false
            void clear (memory_order sync = memory_order_seq_cst) volatile noexcept;
            void clear (memory_order sync = memory_order_seq_cst) noexcept;
            

            示例

            #include <iostream>  #include <atomic>  #include <vector>  #include <thread>  #include <sstream> 
            std::atomic_flag 
            lock = ATOMIC_FLAG_INIT;    std::stringstream stream; 
            int main() {     std::vector<std::thread> vec_thread;      for ( int i = 0; i < 10; i++ ) {         vec_thread.push_back( std::thread( [](int x){             while ( lock.test_and_set() );              stream << "thread#" << x << " \n ";                   lock.clear();         }, i));      }
                
            for ( int i = 0; i < 10; i++ ){          vec_thread[i].join();     }
                std::cout 
            << stream.str();       return 0;  }

            基于std::atom_flag類的C風格API

            bool atomic_flag_test_and_set (volatile atomic_flag* obj) noexcept;
            bool atomic_flag_test_and_set (atomic_flag* obj) noexcept;
            bool atomic_flag_test_and_set (volatile atomic_flag* obj, memory_order sync) noexcept;
            bool atomic_flag_test_and_set (atomic_flag* obj, memory_order sync) noexcept;
            void atomic_flag_clear (volatile atomic_flag* obj) noexcept;
            void atomic_flag_clear (atomic_flag* obj) noexcept;
            void atomic_flag_clear (volatile atomic_flag* obj, memory_order sync) noexcept;
            void atomic_flag_clear (atomic_flag* obj, memory_order sync) noexcept;
            

            std::atomic類模板

            std::atomic 比 std::atomic_flag 功能更加完善, 因此有更多的成員方法.

            template < class T > struct atomic {
                
            // 缺省構造,  std::atomic 對象處于未初始化(uninitialized)狀態     atomic() = default
                
            // 普通構造函數, 由類型T初始化一個 std::atomic對象     constexpr atomic(T)) noexcept; 
                
            // 禁止拷貝構造     atomic(const atomic &= delete; 
                
            // 禁止拷貝賦值     atomic & operator=(const atomic &= delete;      atomic & operator=(const atomic &volatile = delete;
                
            // 從類型T的隱式轉換賦值     T operator=(T) volatile noexcept;      T operator=(T) noexcept;

                
            // 判斷該 std::atomic對象是否具備lock-free的特性. 如果某個對象滿足 lock-free 特性, 在多個線程訪問該對象時不會導致線程阻塞.      bool is_lock_free() const volatile;      bool is_lock_free() const;

                
            // 修改被封裝的值, 參數 sync 指定內存序     void store(T, memory_order = memory_order_seq_cst) volatile;     void store(T, memory_order = memory_order_seq_cst);

                
            // 讀取被封裝的值, 參數 sync 設置內存序     T load(memory_order = memory_order_seq_cst) const volatile;     T load(memory_order = memory_order_seq_cst) const;
                
            // 與load()的功能類似, 也是讀取被封裝的值     operator T() const volatile;      operator T() const;
                
            // 讀取并修改被封裝的值, 用val指定的值替換該原子對象封裝的值, 并返回該原子對象之前封裝的值, 整個過程是原子的, 因此exchange 操作也稱為 read-modify-write 操作.     T exchange(T, memory_order = memory_order_seq_cst) volatile;     T exchange(T, memory_order = memory_order_seq_cst);
                
            // 比較被封裝的值(weak)與參數expected所指定的值的物理內容是否相等, 如果相等, 則用val替換原子對象的舊值;如果不相等, 則用原子對象的舊值替換expected.     // 因此調用該函數之后, 如果被該原子對象封裝的值與參數 expected 所指定的值不相等, expected 中的內容就是原子對象的舊值.      // 整個操作是原子的, 當前線程讀取和修改該原子對象時, 別的線程不能對讀取和修改該原子對象.      // 與compare_exchange_strong不同, weak版本的compare-and-exchange操作允許spuriously 返回 false, 即原子對象所封裝的值與參數 expected 的物理內容相同, 但卻仍然返回 false, 這在使用循環操作的算法下是可以接受的, 并且在一些平臺下weak版本的性能更     bool compare_exchange_weak (T& expected, T val, memory_order sync = memory_order_seq_cst) volatile noexcept;     bool compare_exchange_weak (T& expected, T val, memory_order sync = memory_order_seq_cst) noexcept;
                
            // 功能同上. 內存序(Memory Order)的選擇取決于比較操作結果, 如果比較結果為 true(即原子對象的值等于 expected), 則選擇參數 success 指定的內存序, 否則選擇參數 failure 所指定的內存序.     bool compare_exchange_weak (T& expected, T val,  memory_order success, memory_order failure) volatile noexcept;     bool compare_exchange_weak (T& expected, T val, memory_order success, memory_order failure) noexcept;
                
            // 與weak版本的差別在于, 如果原子對象所封裝的值與參數 expected 的物理內容相同, 比較操作一定會為 true.      bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst) volatile;      bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst);     bool compare_exchange_strong(T &, T, memory_order, memory_order) volatile;     bool compare_exchange_strong(T &, T, memory_order, memory_order);
            };

            C++11標準庫std::atomic提供了針對整形(integral)和指針類型的特化實現.

            針對整形(integal)的特化, 其中integal 代表了如下類型 charsigned charunsigned charshortunsigned shortintunsigned intlongunsigned longlong longunsigned long longchar16_tchar32_twchar_t :

            template <> struct atomic<integral> {     bool is_lock_free() const volatile;     bool is_lock_free() const;
                
            void store(integral, memory_order = memory_order_seq_cst) volatile;     void store(integral, memory_order = memory_order_seq_cst);
                integral load(memory_order 
            = memory_order_seq_cst) const volatile;     integral load(memory_order = memory_order_seq_cst) const;
                
            operator integral() const volatile;     operator integral() const;
                integral exchange(integral, memory_order 
            = memory_order_seq_cst) volatile;     integral exchange(integral, memory_order = memory_order_seq_cst);
                
            bool compare_exchange_weak(integral&, integral, memory_order, memory_order) volatile;     bool compare_exchange_weak(integral&, integral, memory_order, memory_order);
                
            bool compare_exchange_strong(integral&, integral, memory_order, memory_order) volatile;     bool compare_exchange_strong(integral&, integral, memory_order, memory_order);
                
            bool compare_exchange_weak(integral&, integral, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_weak(integral&, integral, memory_order = memory_order_seq_cst);
                
            bool compare_exchange_strong(integral&, integral, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_strong(integral&, integral, memory_order = memory_order_seq_cst);
                
            //原子對象的封裝值加 val, 并返回原子對象的舊值. 整個過程是原子的     integral fetch_add(integral, memory_order = memory_order_seq_cst) volatile;     integral fetch_add(integral, memory_order = memory_order_seq_cst);
                integral fetch_sub(integral, memory_order 
            = memory_order_seq_cst) volatile;     integral fetch_sub(integral, memory_order = memory_order_seq_cst);
                integral fetch_and(integral, memory_order 
            = memory_order_seq_cst) volatile;     integral fetch_and(integral, memory_order = memory_order_seq_cst);
                integral fetch_or(integral, memory_order 
            = memory_order_seq_cst) volatile;     integral fetch_or(integral, memory_order = memory_order_seq_cst);
                integral fetch_xor(integral, memory_order 
            = memory_order_seq_cst) volatile;     integral fetch_xor(integral, memory_order = memory_order_seq_cst);
                atomic() 
            = default;     constexpr atomic(integral);     atomic(const atomic&= delete;
                atomic
            & operator=(const atomic&= delete;     atomic& operator=(const atomic&volatile = delete;
                integral 
            operator=(integral) volatile;     integral operator=(integral);
                integral 
            operator++(intvolatile//后綴++     integral operator++(int);
                integral 
            operator--(intvolatile//后綴--     integral operator--(int);
                integral 
            operator++() volatile//前綴++     integral operator++();
                integral 
            operator--() volatile//前綴--     integral operator--();
                integral 
            operator+=(integral) volatile;     integral operator+=(integral);
                integral 
            operator-=(integral) volatile;     integral operator-=(integral);
                integral 
            operator&=(integral) volatile;     integral operator&=(integral);
                integral 
            operator|=(integral) volatile;     integral operator|=(integral);
                integral 
            operator^=(integral) volatile;     integral operator^=(integral); };

            針對指針的特化:

            template <class T> struct atomic<T*> {     bool is_lock_free() const volatile;     bool is_lock_free() const;
                
            void store(T*, memory_order = memory_order_seq_cst) volatile;     void store(T*, memory_order = memory_order_seq_cst);
                T
            * load(memory_order = memory_order_seq_cst) const volatile;     T* load(memory_order = memory_order_seq_cst) const;
                
            operator T*() const volatile;     operator T*() const;
                T
            * exchange(T*, memory_order = memory_order_seq_cst) volatile;     T* exchange(T*, memory_order = memory_order_seq_cst);
                
            bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile;     bool compare_exchange_weak(T*&, T*, memory_order, memory_order);
                
            bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile;     bool compare_exchange_strong(T*&, T*, memory_order, memory_order);
                
            bool compare_exchange_weak(T*&, T*, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_weak(T*&, T*, memory_order = memory_order_seq_cst);
                
            bool compare_exchange_strong(T*&, T*, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_strong(T*&, T*, memory_order = memory_order_seq_cst);
                T
            * fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) volatile;     T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst);
                T
            * fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) volatile;     T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst);
                atomic() 
            = default;     constexpr atomic(T*);     atomic(const atomic&= delete;
                atomic
            & operator=(const atomic&= delete;     atomic& operator=(const atomic&volatile = delete;
                T
            * operator=(T*volatile;     T* operator=(T*);
                T
            * operator++(intvolatile;     T* operator++(int);
                T
            * operator--(intvolatile;     T* operator--(int);
                T
            * operator++() volatile;     T* operator++();
                T
            * operator--() volatile;     T* operator--();
                T
            * operator+=(ptrdiff_t) volatile;     T* operator+=(ptrdiff_t);
                T
            * operator-=(ptrdiff_t) volatile;     T* operator-=(ptrdiff_t); };

            范例

            #include <iostream> #include <atomic> #include <vector> #include <thread> #include <sstream>
            std::atomic
            <int> foo(0);
            void set_foo(int x){     foo = x; }
            void print_foo(){     while (foo == 0) {         std::this_thread::yield();     }     std::cout << "x: " << foo << std::endl; }
            int main() {     std::thread print_th(print_foo);     std::thread set_th(set_foo, 10);     print_th.join();     set_th.join();     return 0; }

            基于std::atomic 類模板的C風格API

            template <class T> bool atomic_is_lock_free (const volatile atomic<T>* obj) noexcept;
            template <class T> bool atomic_is_lock_free (const atomic<T>* obj) noexcept;
            bool atomic_is_lock_free (const volatile A* obj) noexcept;
            bool atomic_is_lock_free (const A* obj) noexcept;
            //初始化原子對象. 如果對一個已初始化的原子對象再次調用 atomic_init(), 則會導致未定義行為(undefined behavior)
            template <class T> void atomic_init (volatile atomic<T>* obj, T val) noexcept;
            template <class T> void atomic_init (atomic<T>* obj, T val) noexcept;
            void atomic_init (volatile A* obj, T val) noexcept;
            void atomic_init (A* obj, T val) noexcept;
            template <class T> void atomic_store (volatile atomic<T>* obj, T val) noexcept;
            template <class T> void atomic_store (atomic<T>* obj, T val) noexcept;
            void atomic_store (volatile A* obj, T val) noexcept;
            void atomic_store (A* obj, T val) noexcept;
            template <class T> T atomic_load (const volatile atomic<T>* obj) noexcept;
            template <class T> T atomic_load (const atomic<T>* obj) noexcept;
            T atomic_load (const volatile A* obj) noexcept;
            T atomic_load (const A* obj) noexcept;
            template <class T> T atomic_load_explicit (const volatile atomic<T>* obj, memory_order sync) noexcept;
            template <class T> T atomic_load_explicit (const atomic<T>* obj, memory_order sync) noexcept;
            T atomic_load_explicit (const volatile A* obj, memory_order sync) noexcept;
            T atomic_load_explicit (const A* obj, memory_order sync) noexcept;
            template <class T> T atomic_exchange (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_exchange (atomic<T>* obj, T val) noexcept;
            T atomic_exchange (volatile A* obj, T val) noexcept;
            T atomic_exchange (A* obj, T val) noexcept;
            template <class T> T atomic_store_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_store_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            T atomic_store_explicit (volatile A* obj, T val, memory_order sync) noexcept;
            T atomic_store_explicit (A* obj, T val, memory_order sync) noexcept;
            template <class T> bool atomic_compare_exchange_weak (volatile atomic<T>* obj, T* expected, T val) noexcept;
            template <class T> bool atomic_compare_exchange_weak (atomic<T>* obj, T* expected, T val) noexcept;
            bool atomic_compare_exchange_weak (volatile A* obj, T* expected, T val) noexcept;
            bool atomic_compare_exchange_weak (A* obj, T* expected, T val) noexcept;
            template <class T> bool atomic_compare_exchange_weak_explicit (volatile atomic<T>* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
            template <class T> bool atomic_compare_exchange_weak_explicit (atomic<T>* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
            bool atomic_compare_exchange_weak_explicit (volatile A* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
            bool atomic_compare_exchange_weak_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
            template <class T> bool atomic_compare_exchange_strong (volatile atomic<T>* obj, T* expected, T val) noexcept;
            template <class T> bool atomic_compare_exchange_strong (atomic<T>* obj, T* expected, T val) noexcept;
            bool atomic_compare_exchange_strong (volatile A* obj, T* expected, T val) noexcept;
            bool atomic_compare_exchange_strong (A* obj, T* expected, T val) noexcept;
            template <class T> bool atomic_compare_exchange_strong_explicit (volatile atomic<T>* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
            template <class T> bool atomic_compare_exchange_strong_explicit (atomic<T>* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
            bool atomic_compare_exchange_strong_explicit (volatile A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
            bool atomic_compare_exchange_strong_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
            template <class T> T atomic_fetch_add (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_fetch_add (atomic<T>* obj, T val) noexcept;
            template <class U> U* atomic_fetch_add (volatile atomic<U*>* obj, ptrdiff_t val) noexcept;
            template <class U> U* atomic_fetch_add (atomic<U*>* obj, ptrdiff_t val) noexcept;
            T atomic_fetch_add (volatile A* obj, M val) noexcept;
            T atomic_fetch_add (A* obj, M val) noexcept;
            template <class T> T atomic_fetch_add_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_add_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class U> U* atomic_fetch_add_explicit (volatile atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
            template <class U> U* atomic_fetch_add_explicit (atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
            T atomic_fetch_add_explicit (volatile A* obj, M val, memory_order sync) noexcept;
            T atomic_fetch_add_explicit (A* obj, M val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_sub (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_fetch_sub (atomic<T>* obj, T val) noexcept;
            template <class U> U* atomic_fetch_sub (volatile atomic<U*>* obj, ptrdiff_t val) noexcept;
            template <class U> U* atomic_fetch_sub (atomic<U*>* obj, ptrdiff_t val) noexcept;
            T atomic_fetch_sub (volatile A* obj, M val) noexcept;
            T atomic_fetch_sub (A* obj, M val) noexcept;
            template <class T> T atomic_fetch_sub_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_sub_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class U> U* atomic_fetch_sub_explicit (volatile atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
            template <class U> U* atomic_fetch_sub_explicit (atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
            T atomic_fetch_sub_explicit (volatile A* obj, M val, memory_order sync) noexcept;
            T atomic_fetch_sub_explicit (A* obj, M val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_and (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_fetch_and (atomic<T>* obj, T val) noexcept;
            T atomic_fetch_and (volatile A* obj, T val) noexcept;
            T atomic_fetch_and (A* obj, T val) noexcept;
            template <class T> T atomic_fetch_and_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_and_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_and_explicit (volatile A* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_and_explicit (A* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_or (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_fetch_or (atomic<T>* obj, T val) noexcept;
            T atomic_fetch_or (volatile A* obj, T val) noexcept;
            T atomic_fetch_or (A* obj, T val) noexcept;
            template <class T> T atomic_fetch_or_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_or_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_or_explicit (volatile A* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_or_explicit (A* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_xor (volatile atomic<T>* obj, T val) noexcept;
            template <class T> T atomic_fetch_xor (atomic<T>* obj, T val) noexcept;
            T atomic_fetch_xor (volatile A* obj, T val) noexcept;
            T atomic_fetch_xor (A* obj, T val) noexcept;
            template <class T> T atomic_fetch_xor_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
            template <class T> T atomic_fetch_xor_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_xor_explicit (volatile A* obj, T val, memory_order sync) noexcept;
            T atomic_fetch_xor_explicit (A* obj, T val, memory_order sync) noexcept;
            

            附錄

            與原子對象初始化相關的宏:

            • ATOMIC_VAR_INIT(val):初始化 std::atomic 對象.
            • ATOMIC_FLAG_INIT:初始化 std::atomic_flag 對象.

            引用記錄

            李白的blog
            256code

            posted on 2022-10-14 16:36 Khan 閱讀(205) 評論(0)  編輯 收藏 引用

            一本一本久久aa综合精品| 亚洲欧美成人综合久久久 | 精品熟女少妇a∨免费久久| 久久99精品免费一区二区| 久久99国产精一区二区三区| 熟妇人妻久久中文字幕| 大香伊人久久精品一区二区| 欧美粉嫩小泬久久久久久久| 久久精品国产第一区二区| 国产精品久久久久乳精品爆 | 久久国产高潮流白浆免费观看| 婷婷国产天堂久久综合五月| 久久亚洲天堂| 亚洲国产成人久久精品99| 久久男人中文字幕资源站| 久久久久久毛片免费看| 久久免费视频6| 香蕉久久夜色精品国产尤物| 久久热这里只有精品在线观看| 久久国产精品无| 精品国产乱码久久久久久呢| 午夜精品久久久久久久| 久久超乳爆乳中文字幕| 免费国产99久久久香蕉| 久久99精品久久久久久噜噜 | 久久久久亚洲av成人网人人软件| 久久WWW免费人成一看片| 中文字幕乱码人妻无码久久| 久久99国产综合精品女同| 久久综合九色综合精品| 日本国产精品久久| 久久国产免费直播| 欧美777精品久久久久网| 久久久久国色AV免费观看| 亚洲伊人久久大香线蕉综合图片| 99久久精品国产麻豆| 久久久精品久久久久久 | 岛国搬运www久久| 四虎国产精品成人免费久久| 成人久久综合网| 综合久久一区二区三区|