FreeBSD Manual Pages
std::atomic_thread_fence(3) C++ Standard Libary std::atomic_thread_fence(3) NAME std::atomic_thread_fence - std::atomic_thread_fence Synopsis Defined in header <atomic> extern "C" void atomic_thread_fence( std::memory_order order ) (since C++11) noexcept; Establishes memory synchronization ordering of non-atomic and re- laxed atomic accesses, as instructed by order, without an associated atomic oper- ation. Note however, that at least one atomic operation is required to set up the synchronization, as described below. Fence-atomic synchronization A release fence F in thread A synchronizes-with atomic acquire oper- ation Y in thread B, if * there exists an atomic store X (with any memory order) * Y reads the value written by X (or the value would be written by release sequence headed by X if X were a release operation) * F is sequenced-before X in thread A In this case, all non-atomic and relaxed atomic stores that are se- quenced-before F in thread A will happen-before all non-atomic and relaxed atomic loads from the same locations made in thread B after Y. Atomic-fence synchronization An atomic release operation X in thread A synchronizes-with an ac- quire fence F in thread B, if * there exists an atomic read Y (with any memory order) * Y reads the value written by X (or by the release sequence headed by X) * Y is sequenced-before F in thread B In this case, all non-atomic and relaxed atomic stores that are se- quenced-before X in thread A will happen-before all non-atomic and relaxed atomic loads from the same locations made in thread B after F. Fence-fence synchronization A release fence FA in thread A synchronizes-with an acquire fence FB in thread B, if * There exists an atomic object M, * There exists an atomic write X (with any memory order) that mod- ifies M in thread A * FA is sequenced-before X in thread A * There exists an atomic read Y (with any memory order) in thread B * Y reads the value written by X (or the value would be written by release sequence headed by X if X were a release operation) * Y is sequenced-before FB in thread B In this case, all non-atomic and relaxed atomic stores that are se- quenced-before FA in thread A will happen-before all non-atomic and relaxed atomic loads from the same locations made in thread B after FB Parameters order - the memory ordering executed by this fence Return value (none) Notes On x86 (including x86-64), atomic_thread_fence functions issue no CPU instructions and only affect compile-time code motion, except for std::atomic_thread_fence(std::memory_order::seq_cst), which issues the full memory fence instruction MFENCE (see C++11 mappings for other architec- tures). atomic_thread_fence imposes stronger synchronization constraints than an atomic store operation with the same std::memory_order. While an atomic store-release operation prevents all preceding reads and writes from moving past the store-release, an atomic_thread_fence with memory_order_release or- dering prevents all preceding reads and writes from moving past all subsequent stores. Fence-fence synchronization can be used to add synchronization to a sequence of several relaxed atomic operations, for example //Global std::string computation(int); void print( std::string ); std::atomic<int> arr[3] = { -1, -1, -1 }; std::string data[1000]; //non-atomic data // Thread A, compute 3 values void ThreadA( int v0, int v1, int v2 ) { //assert( 0 <= v0, v1, v2 < 1000 ); data[v0] = computation(v0); data[v1] = computation(v1); data[v2] = computation(v2); std::atomic_thread_fence(std::memory_order_release); std::atomic_store_explicit(&arr[0], v0, std::memory_order_relaxed); std::atomic_store_explicit(&arr[1], v1, std::memory_order_relaxed); std::atomic_store_explicit(&arr[2], v2, std::memory_order_relaxed); } // Thread B, prints between 0 and 3 values already computed. void ThreadB() { int v0 = std::atomic_load_explicit(&arr[0], std::memory_order_re- laxed); int v1 = std::atomic_load_explicit(&arr[1], std::memory_order_re- laxed); int v2 = std::atomic_load_explicit(&arr[2], std::memory_order_re- laxed); std::atomic_thread_fence(std::memory_order_acquire); // v0, v1, v2 might turn out to be -1, some or all of them. // otherwise it is safe to read the non-atomic data because of the fences: if( v0 != -1 ) { print( data[v0] ); } if( v1 != -1 ) { print( data[v1] ); } if( v2 != -1 ) { print( data[v2] ); } } Example Scan an array of mailboxes, and process only the ones intended for us, without unnecessary synchronization. This example uses atomic-fence synchro- nization. const int num_mailboxes = 32; std::atomic<int> mailbox_receiver[num_mailboxes]; std::string mailbox_data[num_mailboxes]; // The writer threads update non-atomic shared data // and then update mailbox_receiver[i] as follows mailbox_data[i] = ...; std::atomic_store_explicit(&mailbox_receiver[i], receiver_id, std::memory_order_release); // Reader thread needs to check all mailbox[i], but only needs to sync with one for (int i = 0; i < num_mailboxes; ++i) { if (std::atomic_load_explicit(&mailbox_receiver[i], std::mem- ory_order_relaxed) == my_id) { std::atomic_thread_fence(std::memory_order_acquire); // syn- chronize with just one writer do_work( mailbox_data[i] ); // guaranteed to observe every- thing done in the writer thread before // the atomic_store_explicit() } } See also memory_order defines memory ordering constraints for the given atomic (C++11) operation (enum) atomic_signal_fence fence between a thread and a signal handler exe- cuted in the same (C++11) thread (function) http://cppreference.com 2022.07.31 std::atomic_thread_fence(3)
NAME | Synopsis | Parameters | Return value | Notes | Example | See also
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::atomic_thread_fence&sektion=3&manpath=FreeBSD+Ports+15.0>
