do {
x = foo.load(std::memory_order_relaxed); // get value atomically
} while (x == 0);
std::cout << "foo: " << x << '\n';
}
int test_atomic_load()
{
// atomic::load: Returns the contained value.
// The operation is atomic and follows the memory ordering specified by sync.
std::thread first(print_foo);
std::thread second(set_foo, 10);
first.join();
second.join();
return 0;
}
////////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/atomic/atomic/operator=/
std::atomic foo_ = 0;
void set_foo_(int x)
{
foo_ = x;
}
void print_foo_()
{
while (foo_ == 0) { // wait while foo_=0
std::this_thread::yield();
}
std::cout << "foo_: " << foo_ << '\n';
}
int test_atomic_operator()
{
// atomic::operator=: Replaces the stored value by val.
// This operation is atomic and uses sequential consistency (memory_order_seq_cst).
// To modify the value with a different memory ordering
std::thread first(print_foo_);
std::thread second(set_foo_, 10);
first.join();
second.join();
return 0;
}
///////////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/atomic/atomic/store/
int test_atomic_store()
{
// atomic::store: Replaces the contained value with val.
// The operation is atomic and follows the memory ordering specified by sync.
std::thread first(print_foo);
std::thread second(set_foo, 10);
first.join();
second.join();
return 0;
}
/////////////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/atomic/atomic_flag/clear/
std::atomic_flag lock_stream = ATOMIC_FLAG_INIT;
std::stringstream stream;
void append_number(int x)
{
while (lock_stream.test_and_set()) {}
stream << "thread #" << x << '\n';
lock_stream.clear();
}
int test_atomic_flag_atomic_clear()
{
// atomic_flag::clear: Clears the atomic_flag (i.e., sets it to false)
//Clearing the atomic_flag makes the next call to member atomic_flag::test_and_set on this object return false.
// The operation is atomic and follows the memory ordering specified by sync.
// atomic_flag::test_and_set: Sets the atomic_flag and returns whether it was already set immediately before the call
// The entire operation is atomic (an atomic read-modify-write operation): the value is not affected by other threads
// between the instant its value is read (to be returned) and the moment it is modified by this function.
std::vector threads;
for (int i = 1; i <= 10; ++i) threads.push_back(std::thread(append_number, i));
for (auto& th : threads) th.join();
std::cout << stream.str();
return 0;
}
} // namespace atomic
|