Namespaces
Variants
Views
Actions

std::atomic<T>::operator++,++(int),--,--(int)

From cppreference.com
< cpp‎ | atomic‎ | atomic
 
 
Concurrency support library
Threads
(C++11)
(C++20)
(C++20)
this_thread namespace
(C++11)
(C++11)
(C++11)
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11)(deprecated in C++20)
(C++11)(deprecated in C++20)
Free functions for atomic operations
Free functions for atomic flags
Memory ordering
Mutual exclusion
(C++11)
Generic lock management
(C++11)
(C++11)
(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
Condition variables
(C++11)
Semaphores
Latches and barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
 
 
T operator++() noexcept;
T operator++() volatile noexcept;
(1) (member only of atomic<Integral> template specialization)
(since C++11)
T* operator++() noexcept;
T* operator++() volatile noexcept;
(1) (member only of atomic<T*> template specialization)
(since C++11)
T operator++( int ) noexcept;
T operator++( int ) volatile noexcept;
(2) (member only of atomic<Integral> template specialization)
(since C++11)
T* operator++( int ) noexcept;
T* operator++( int ) volatile noexcept;
(2) (member only of atomic<T*> template specialization)
(since C++11)
T operator--() noexcept;
T operator--() volatile noexcept;
(3) (member only of atomic<Integral> template specialization)
(since C++11)
T* operator--() noexcept;
T* operator--() volatile noexcept;
(3) (member only of atomic<T*> template specialization)
(since C++11)
T operator--( int ) noexcept;
T operator--( int ) volatile noexcept;
(4) (member only of atomic<Integral> template specialization)
(since C++11)
T* operator--( int ) noexcept;
T* operator--( int ) volatile noexcept;
(4) (member only of atomic<T*> template specialization)
(since C++11)

Atomically increments or decrements the current value. The operation is read-modify-write operation.

1) Performs atomic pre-increment. Equivalent to fetch_add(1)+1.
2) Performs atomic post-increment. Equivalent to fetch_add(1).
3) Performs atomic pre-decrement. Equivalent to fetch_sub(1)-1
4) Performs atomic post-decrement. Equivalent to fetch_sub(1).

For signed Integral types, arithmetic is defined to use two’s complement representation. There are no undefined results.

For T* types, the result may be an undefined address, but the operations otherwise have no undefined behavior. The program is ill-formed if T is not an object type.

The volatile-qualified versions are deprecated if std::atomic<T>::is_always_lock_free is false.

(since C++20)

Contents

[edit] Parameters

(none)

[edit] Return value

1,3) The value of the atomic variable after the modification. Formally, the result of incrementing/decrementing the value immediately preceding the effects of this function in the modification order of *this.
2,4) The value of the atomic variable before the modification. Formally, the value immediately preceding the effects of this function in the modification order of *this.

[edit] Notes

Unlike most pre-increment and pre-decrement operators, the pre-increment and pre-decrement operators for atomic types do not return a reference to the modified object. They return a copy of the stored value instead.

[edit] Example

#include <atomic>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <random>
#include <thread>
 
std::atomic<int> atomic_count{0};
std::atomic<int> atomic_writes{0};
 
constexpr int global_max_count{72};
constexpr int writes_per_line{8};
constexpr int max_delay{100};
 
template<int Max> int random_value()
{
    static std::uniform_int_distribution<int> distr{1, Max};
    static std::random_device engine;
    static std::mt19937 noise{engine()};
    static std::mutex rand_mutex;
    std::lock_guard μ{rand_mutex};
    return distr(noise);
}
 
int main()
{
    auto work = [](const char id)
    {
        for (int count{}; (count = ++atomic_count) <= global_max_count;) {
            std::this_thread::sleep_for(
                std::chrono::milliseconds(random_value<max_delay>()));
 
            bool new_line{false};
            if (++atomic_writes % writes_per_line == 0) {
                new_line = true;
            }
            // print thread `id` and `count` value
            {
                static std::mutex cout_mutex;
                std::lock_guard m{cout_mutex};
                std::cout << "[" << id << "] " << std::setw(3) << count << " │ "
                          << (new_line ? "\n" : "") << std::flush;
            }
        }
    };
 
    std::jthread j1(work, 'A'), j2(work, 'B'), j3(work, 'C'), j4(work, 'D');
}

Possible output:

[B]   3 │ [D]   1 │ [C]   2 │ [D]   6 │ [A]   4 │ [B]   5 │ [B]  10 │ [D]   8 │
[C]   7 │ [A]   9 │ [A]  14 │ [B]  11 │ [D]  12 │ [C]  13 │ [A]  15 │ [C]  18 │
[D]  17 │ [B]  16 │ [C]  20 │ [C]  23 │ [D]  21 │ [A]  19 │ [C]  24 │ [B]  22 │
[A]  26 │ [C]  27 │ [D]  25 │ [C]  30 │ [B]  28 │ [D]  31 │ [A]  29 │ [C]  32 │
[B]  33 │ [D]  34 │ [B]  37 │ [B]  39 │ [B]  40 │ [A]  35 │ [C]  36 │ [C]  43 │
[D]  38 │ [A]  42 │ [B]  41 │ [A]  46 │ [B]  47 │ [C]  44 │ [A]  48 │ [D]  45 │
[C]  50 │ [D]  52 │ [B]  49 │ [D]  54 │ [C]  53 │ [A]  51 │ [B]  55 │ [D]  56 │
[D]  60 │ [A]  58 │ [C]  57 │ [D]  61 │ [C]  63 │ [B]  59 │ [D]  64 │ [C]  65 │
[A]  62 │ [D]  67 │ [B]  66 │ [C]  68 │ [D]  70 │ [C]  72 │ [B]  71 │ [A]  69 │

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
P0558R1 C++11 arithmetic permitted on pointers to cv void or function made ill-formed

[edit] See also

atomically adds the argument to the value stored in the atomic object and obtains the value held previously
(public member function) [edit]
atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously
(public member function) [edit]
adds, subtracts, or performs bitwise AND, OR, XOR with the atomic value
(public member function) [edit]