public member function
<atomic>

std::atomic::exchange

T exchange (T val, memory_order sync = memory_order_seq_cst) volatile noexcept;
T exchange (T val, memory_order sync = memory_order_seq_cst) noexcept;
Access and modify contained value
Replaces the contained value by val and returns the value it had immediately before.

The entire operation is atomic (an atomic read-modify-write operation): the value is not affected by other threads between the instant its value is read (to be returned) and the moment it is modified by this function.

Parameters

val
Value to copy to the contained object.
T is atomic's template parameter (the type of the contained value).
sync
Synchronization mode for the operation.
This can be any of the possible values of the enum type memory_order:
valuememory orderdescription
memory_order_relaxedRelaxedNo synchronization of side effects.
memory_order_consumeConsume Synchronizes the visible side effects on values carrying dependencies from the last release or sequentially consistent operation.
memory_order_acquireAcquireSynchronizes all visible side effects from the last release or sequentially consistent operation.
memory_order_releaseReleaseSynchronizes side effects with the next consume or acquire operation.
memory_order_acq_relAcquire/ReleaseReads as an acquire operation and writes as a release operation (as described above).
memory_order_seq_cstSequentially consistentSynchronizes all visible side effects with the other sequentially consistent operations, following a single total order.

Return value

The contained value before the call.
T is atomic's template parameter (the type of the contained value).

Example

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
// atomic::exchange example
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector

std::atomic<bool> ready (false);
std::atomic<bool> winner (false);

void count1m (int id) {
  while (!ready) {}                  // wait for the ready signal
  for (int i=0; i<1000000; ++i) {}   // go!, count to 1 million
  if (!winner.exchange(true)) { std::cout << "thread #" << id << " won!\n"; }
};

int main ()
{
  std::vector<std::thread> threads;
  std::cout << "spawning 10 threads that count to 1 million...\n";
  for (int i=1; i<=10; ++i) threads.push_back(std::thread(count1m,i));
  ready = true;
  for (auto& th : threads) th.join();

  return 0;
}


Possible output (other threads may win):
spawning 10 threads that count to 1 million...
thread #7 won!

Data races

No data races (atomic operation). Memory order specified by argument sync.

Exception safety

No-throw guarantee: never throws exceptions.

See also