Parent directory
atomic.cpp
Makefile
rel-acq.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
using namespace std;
using namespace std::chrono;
struct wallet {
std::atomic<uint64_t> money{0};
operator uint64_t() const {
return money;
// return money.load(std::memory_order_relaxed);
}
wallet& operator++() {
++money;
// money.fetch_add(1, std::memory_order_relaxed);
return *this;
}
};
// Built-in types are always lock-free, but custom structures may not be.
// static_assert(atomic<uint64_t>::is_always_lock_free);
void f(wallet& sum, uint64_t count) {
while (count--) {
++sum;
}
}
int main() {
constexpr uint64_t count = 1'000'000;
wallet sum;
auto time0 = high_resolution_clock::now();
thread t1 { f, ref(sum), count };
thread t2 { f, ref(sum), count };
t1.join();
t2.join();
auto time1 = high_resolution_clock::now();
auto dt = duration_cast<microseconds>(time1 - time0);
cout << "elapsed: " << dt.count() << " microsec\n";
cout << "result: " << sum << '\n';
}CC = g++
CXX = g++
CFLAGS = -Wall -g
CXXFLAGS = -Wall -g -std=c++20 -pthread
LDFLAGS = -pthread
LDLIBS =
executables = atomic
.PHONY: default
default: $(executables)
atomic:
.PHONY: clean
clean:
rm -f a.out core *.o $(executables)
.PHONY: all
all: clean default#include <atomic>
#include <cassert>
#include <string>
#include <thread>
std::atomic<uint64_t> x{0};
//uint64_t x{0};
std::atomic<uint64_t> y{0};
void producer() {
for (size_t i = 0; i < 1000'000'000; ++i) {
x.fetch_add(1, std::memory_order_relaxed);
//++x;
//y.fetch_add(1, std::memory_order_release);
y.fetch_add(1, std::memory_order_relaxed);
}
}
void consumer() {
for (size_t i = 0; i < 1000'000'000; ++i) {
int64_t yy = y.load(std::memory_order_acquire);
//uint64_t yy = y.load(std::memory_order_relaxed);
assert(x.load(std::memory_order_relaxed) >= yy);
//assert(x >= yy);
}
}
int main()
{
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
}