Reputation: 11
I would like to know how to make the following function in a whole atomic.
With my code, I believe there can be a situation that two threads both pass the condition, and return 0,1 respectively right?
static std::atomic<uintV> shared_v (0);
int compare_increment() {
if (shared_v >= 10) {
return -1;
}
return shared_v++;
Any help would be appreciated.
Upvotes: 1
Views: 1731
Reputation: 54353
I wrote one for a bit of fun.
$ cat compare-exchange-atomic-test.cpp
#include <array>
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> value{0};
std::atomic<int> loops{0};
int comparison_target = 10;
void f() {
int v;
do {
v = value;
if (v < comparison_target) {
return;
}
++loops;
} while (!value.compare_exchange_weak(v, v + 1));
}
void g() {
int i;
for (i = 0; i < 1000; ++i) {
f();
}
}
int main(int argc, char *argv[]) {
if (argc > 1) {
comparison_target = std::stoi(argv[1]);
}
std::array<std::thread, 64> threads;
for (auto &x : threads) {
x = std::thread(g);
}
for (auto &x : threads) {
x.join();
}
std::cout << value << ' ' << comparison_target << ' ' << loops << std::endl;
return 0;
}
$ g++ -Wall -W -pedantic -g -O3 -flto -fno-fat-lto-objects -mcpu=native -DNDEBUG -pthread -MMD -fPIC -fPIE -std=c++17 compare-exchange-atomic-test.cpp -pthread -flto -fno-fat-lto-objects -o compare-exchange-atomic-test
$ ./compare-exchange-atomic-test 1
0 1 0
$ ./compare-exchange-atomic-test 0
64000 0 455100
$ ./compare-exchange-atomic-test 0
64000 0 550596
Upvotes: 1
Reputation: 58741
You can use compare_exchange_weak
in a loop to achieve this sort of read-modify-write effect without a mutex.
Example (untested):
int compare_increment() {
uintV old = shared_v.load();
do {
if (old >= 10)
return -1;
} while (!shared_v.compare_exchange_weak(old, old+1));
return old;
}
Upvotes: 1