stdatomic

How do memory_order_seq_cst and memory_order_acq_rel differ?

末鹿安然 提交于 2019-11-28 20:58:45
问题 Stores are release operations and loads are acquire operations for both. I know that memory_order_seq_cst is meant to impose an additional total ordering for all operations, but I'm failing to build an example where it isn't the case if all the memory_order_seq_cst are replaced by memory_order_acq_rel . Do I miss something, or the difference is just a documentation effect, i.e. one should use memory_order_seq_cst if one intend not to play with a more relaxed model and use memory_order_acq_rel

Will two relaxed writes to the same location in different threads always be seen in the same order by other threads?

馋奶兔 提交于 2019-11-28 08:29:12
On the x86 architecture, stores to the same memory location have a total order, e.g., see this video . What are the guarantees in the C++11 memory model? More precisely, in -- Initially -- std::atomic<int> x{0}; -- Thread 1 -- x.store(1, std::memory_order_release); -- Thread 2 -- x.store(2, std::memory_order_release); -- Thread 3 -- int r1 = x.load(std::memory_order_acquire); int r2 = x.load(std::memory_order_acquire); -- Thread 4 -- int r3 = x.load(std::memory_order_acquire); int r4 = x.load(std::memory_order_acquire); would the outcome r1==1, r2==2, r3==2, r4==1 be allowed (on some

Why does g++ still require -latomic

落爺英雄遲暮 提交于 2019-11-28 02:52:29
问题 In 29.5 Atomic types of the C++ Standard November 2014 working draft it states: There is a generic class template atomic. The type of the template argument T shall be trivially copyable (3.9). [ Note: Type arguments that are not also statically initializable may be difficult to use. —end note ] So - as far as I can tell - this: #include <atomic> struct Message { unsigned long int a; unsigned long int b; }; std::atomic<Message> sharedState; int main() { Message tmp{1,2}; sharedState.store(tmp)

Where is the lock for a std::atomic?

大憨熊 提交于 2019-11-27 07:02:31
If a data structure has multiple elements in it, the atomic version of it cannot (always) be lock-free. I was told that this is true for larger types because the CPU can not atomically change the data without using some sort of lock. for example: #include <iostream> #include <atomic> struct foo { double a; double b; }; std::atomic<foo> var; int main() { std::cout << var.is_lock_free() << std::endl; std::cout << sizeof(foo) << std::endl; std::cout << sizeof(var) << std::endl; } the output (Linux/gcc) is: 0 16 16 Since the atomic and foo are the same size, I don't think a lock is stored in the

When do I really need to use atomic<bool> instead of bool? [duplicate]

江枫思渺然 提交于 2019-11-27 06:39:23
This question already has an answer here: Can a bool read/write operation be not atomic on x86? [duplicate] 3 answers Do I have to use atomic<bool> for “exit” bool variable? 3 answers Isn't atomic<bool> redundant because bool is atomic by nature? I don't think it's possible to have a partially modified bool value. When do I really need to use atomic<bool> instead of bool ? No type in C++ is "atomic by nature" unless it is an std::atomic* -something. That's because the standard says so. In practice, the actual hardware instructions that are emitted to manipulate an std::atomic<bool> may (or may

Does std::atomic<std::string> work appropriately?

会有一股神秘感。 提交于 2019-11-27 02:29:32
问题 I am reading through Anthony Williams' "C++ Concurrency in Action" and in Chapter 5, which talks about the new multithreading-aware memory model and atomic operations, and he states: In order to use std::atomic<UDT> for some user-defined UDT , this type must have a trivial copy assignment operator. As I understand it, this means that we can use std::atomic<UDT> if the following returns true: std::is_trivially_copyable<UDT>::value By this logic, we shouldn't be able to use std::string as a

Will two relaxed writes to the same location in different threads always be seen in the same order by other threads?

狂风中的少年 提交于 2019-11-27 02:12:06
问题 On the x86 architecture, stores to the same memory location have a total order, e.g., see this video. What are the guarantees in the C++11 memory model? More precisely, in -- Initially -- std::atomic<int> x{0}; -- Thread 1 -- x.store(1, std::memory_order_release); -- Thread 2 -- x.store(2, std::memory_order_release); -- Thread 3 -- int r1 = x.load(std::memory_order_acquire); int r2 = x.load(std::memory_order_acquire); -- Thread 4 -- int r3 = x.load(std::memory_order_acquire); int r4 = x.load

Acquire/release semantics with 4 threads

泄露秘密 提交于 2019-11-27 01:50:20
问题 I am currently reading C++ Concurrency in Action by Anthony Williams. One of his listing shows this code, and he states that the assertion that z != 0 can fire. #include <atomic> #include <thread> #include <assert.h> std::atomic<bool> x,y; std::atomic<int> z; void write_x() { x.store(true,std::memory_order_release); } void write_y() { y.store(true,std::memory_order_release); } void read_x_then_y() { while(!x.load(std::memory_order_acquire)); if(y.load(std::memory_order_acquire)) ++z; } void

Acquire/release semantics with non-temporal stores on x64

这一生的挚爱 提交于 2019-11-26 22:41:04
I have something like: if (f = acquire_load() == ) { ... use Foo } and: auto f = new Foo(); release_store(f) You could easily imagine an implementation of acquire_load and release_store that uses atomic with load(memory_order_acquire) and store(memory_order_release). But now what if release_store is implemented with _mm_stream_si64, a non-temporal write, which is not ordered with respect to other stores on x64? How to get the same semantics? I think the following is the minimum required: atomic<Foo*> gFoo; Foo* acquire_load() { return gFoo.load(memory_order_relaxed); } void release_store(Foo*

Will two atomic writes to different locations in different threads always be seen in the same order by other threads?

对着背影说爱祢 提交于 2019-11-26 21:06:41
Similar to my previous question, consider this code -- Initially -- std::atomic<int> x{0}; std::atomic<int> y{0}; -- Thread 1 -- x.store(1, std::memory_order_release); -- Thread 2 -- y.store(2, std::memory_order_release); -- Thread 3 -- int r1 = x.load(std::memory_order_acquire); // x first int r2 = y.load(std::memory_order_acquire); -- Thread 4 -- int r3 = y.load(std::memory_order_acquire); // y first int r4 = x.load(std::memory_order_acquire); Is the weird outcome r1==1, r2==0 and r3==2, r4==0 possible in this case under the C++11 memory model? What if I were to replace all std::memory_order