This site explains C++11 atomics and gives an example implementation of an atomic fetch_mult
operation that is not provided by the default std::atomic<T>
types:
#include <atomic>
#include <iostream>
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
T oldValue= shared.load();
// 1
while (!shared.compare_exchange_strong(oldValue, oldValue * mult));
return oldValue;
}
int main(){
std::atomic<int> myInt{5};
std::cout << myInt << std::endl;
fetch_mult(myInt,5);
std::cout << myInt << std::endl;
}
I'm having trouble understanding this function. If fetch_mult
is interrupted at point // 1
by another thread that also calls fetch_mult
, wouldn't one of the threads deadlock since the compare_exchange_strong
will never return true
unless either mult==1
or another thread sets the value back to oldValue
?
For example (T1 and T2 being the respective threads):
oldValue = 5;
oldValue = 5;
compare_exchange_strong
successfully sets the value to 25
compare_exchange_strong
never completes successfully since its oldValue
is still 5
unless somebody else sets the value to 5
againIs my understanding correct? If so, would this be a correct implementation of fetch_mult
?
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
while (true) {
T oldValue = shared.load();
if (shared.compare_exchange_strong(oldValue, oldValue * mult))
return oldValue;
}
}
atomic::compare_exchange_*
loads the current value into the 'expected' parameter if the comparison fails. In your example, in step 4 T1 would fail the compare-exchange and load 25 into oldValue
, and then would succeed on the next iteration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With