std::atomic...,--,--(int)(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

okay so bestie, welcome to the C++ Standard Libary manual πŸ’– this page is all about std::atomic::operator++,++(int),--,--(int), and it’s literally the atomic glow-up of increment/decrement. no cap, every overload is here.

πŸ’– NAME πŸ’–

std::atomic::operator++,++(int),--,--(int) β€” std::atomic::operator++,++(int),--,--(int)

πŸ¦‹ Synopsis πŸ¦‹

          member only of atomic<Integral > specializations
          T operator++() noexcept;                          (1)  (since C++11)
          T operator++() volatile noexcept;                 (2)  (since C++11)
          T operator++( int ) noexcept;                     (3)  (since C++11)
          T operator++( int ) volatile noexcept;            (4)  (since C++11)
          T operator--() noexcept;                          (5)  (since C++11)
          T operator--() volatile noexcept;                 (6)  (since C++11)
          T operator--( int ) noexcept;                     (7)  (since C++11)
          T operator--( int ) volatile noexcept;            (8)  (since C++11)
          member only of atomic<T*> partial specialization
          T* operator++() noexcept;                         (9)  (since C++11)
          T* operator++() volatile noexcept;                (10) (since C++11)
          T* operator++( int ) noexcept;                    (11) (since C++11)
          T* operator++( int ) volatile noexcept;           (12) (since C++11)
          T* operator--() noexcept;                         (13) (since C++11)
          T* operator--() volatile noexcept;                (14) (since C++11)
          T* operator--( int ) noexcept;                    (15) (since C++11)
          T* operator--( int ) volatile noexcept;           (16) (since C++11)

okay so what does it do? It atomically increments or decrements the current value. The operation is a read-modify-write operation. 🫢

  • operator++() performs atomic pre-increment. Equivalent to return fetch_add(1) + 1;.
  • operator++(int) performs atomic post-increment. Equivalent to return fetch_add(1);.
  • operator--() performs atomic pre-decrement. Equivalent to return fetch_sub(1) - 1;.
  • operator--(int) performs atomic post-decrement. Equivalent to return fetch_sub(1);.

1-8) For signed integral types, arithmetic is defined to use two’s complement representation. There are no undefined results.

9-16) The result may be an undefined address, but the operations otherwise have no undefined behavior. If T is not a complete object type, the program is ill-formed.

⚠️ It is deprecated if std::atomic<T>::is_always_lock_free is false and (since C++20) any volatile overload participates in overload resolution.

πŸ’« Return value πŸ’«

operator++() and operator--() return 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.

operator++(int) and operator--(int) return 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.

🌸 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. fr fr, that’s the whole vibe.

πŸ“ Example πŸ“

this example is iconic, bestie β€” here’s the code exactly:

// Run this code

        #include <atomic>
        #include <chrono>
        #include <iomanip>
        #include <iostream>
        #include <mutex>
        #include <random>
        #include <string>
        #include <thread>

        std::atomic<int> atomic_count{0};

        std::mutex cout_mutex;
        int completed_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 lock{rand_mutex};
            return distr(noise);
        }

        int main()
        {
            auto work = [](const std::string id)
            {
                for (int count{}; (count = ++atomic_count) <=
       global_max_count;)
                {
                    std::this_thread::sleep_for(
                        std::chrono::milliseconds(random_value<max_delay>()));

                    // print thread `id` and `count` value
                    {
                        std::lock_guard lock{cout_mutex};

                        const bool new_line = ++completed_writes %
       writes_per_line == 0;

                        std::cout << id << std::setw(3) << count << "  "
                                  << (new_line ? "\n" : "") << std::flush;
                    }
                }
            };

            std::jthread j1(work, "β–‘"), j2(work, "β–’"), j3(work, "β–“"), j4(work,
       "β–ˆ");
        }

🌈 Possible output 🌈

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

πŸ’€ Defect reports πŸ’€

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

  • P0558R1 β€” applied to C++11. Behavior as published: arithmetic permitted on pointers to (possibly cv-qualified) void or function. Correct behavior: made ill-formed.

πŸ‘‘ See also πŸ‘‘

  • fetch_add β€” atomically adds the argument to the value stored in the atomic object and obtains the value held previously (public member function).
  • fetch_sub β€” atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously (public member function).
  • operator+=, operator-= β€” adds to or subtracts from the atomic value (public member function).
  • operator&=, operator|=, operator^= β€” performs bitwise AND, OR, XOR with the atomic value (public member function).

okay bye bestie πŸ’… source/version vibes: http://cppreference.com, date 2024.06.10, and this whole page is std::atomic...,--,--(int)(3). periodt. πŸŽ€

πŸ“¦ where this page comes from