Studying through a book, it explains how to implement more complex operations like operator*
for std::atomic<T>
. Implementation uses compare_exchange_weak
and I think I understood how this works. Now, I implemented things myself, take a look.
#include <type_traits>#include <atomic>#include <iostream>/*template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>std::atomic<T>& operator*=(std::atomic<T>& t1, T t2) { T expected = t1.load(); while(!t1.compare_exchange_weak(expected, expected * t2)) {} return t1;}*/template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>std::atomic<T>& operator*=(std::atomic<T>& t1, T t2) { T expected = t1.load(); t1.compare_exchange_weak(expected, expected * t2); return t1;}int main() { std::atomic<int> t1 = 5; std::atomic<int> t2; t2 = (t1 *= 5).load(); std::cout << "Atomic t1: "<< t1 << "\n"; std::cout << "Atomic t2: "<< t2 << "\n";}
I have two versions of the code, book's version is commented out. I don't get why I should wait on a busy-loop to perform atomic compare_exchange
. In my version, I've just called it on its own line and looking at the generated assembly in Godbolt, both uses
lock cmpxchg dword ptr [rsp + 8], ecx
and looks pretty similar to me. So, why should I need a wait-loop like the one in the book to make this thing atomic? Isn't my version also fine and do work atomically?