The following excerpt from the current draft shows what I mean:
namespace std {
typedef struct atomic_bool {
bool is_lock_free() const volatile;
bool is_lock_free() const;
void store(bool, memory_order = memory_order_seq_cst) volatile;
void store(bool, memory_order = memory_order_seq_cst);
bool load(memory_order = memory_order_seq_cst) const volatile;
bool load(memory_order = memory_order_seq_cst) const;
operator bool() const volatile;
operator bool() const;
bool exchange(bool, memory_order = memory_order_seq_cst) volatile;
bool exchange(bool, memory_order = memory_order_seq_cst);
bool compare_exchange_weak(bool&, bool, memory_order, memory_order) volatile;
bool compare_exchange_weak(bool&, bool, memory_order, memory_order);
bool compare_exchange_strong(bool&, bool, memory_order, memory_order) volatile;
bool compare_exchange_strong(bool&, bool, memory_order, memory_order);
bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst) volatile;
bool compare_exchange_weak(bool&, bool, memory_order = memory_order_seq_cst);
bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst) volatile;
bool compare_exchange_strong(bool&, bool, memory_order = memory_order_seq_cst);
atomic_bool() = default;
constexpr atomic_bool(bool);
atomic_bool(const atomic_bool&) = delete;
atomic_bool& operator=(const atomic_bool&) = delete;
atomic_bool& operator=(const atomic_bool&) volatile = delete;
bool operator=(bool) volatile;
} atomic_bool;
}
Volatile is transitive. Thus, you cannot call a non-volatile member function from a volatile object. On the other hand, calling a volatile member function from a non-volatile object is allowed.
So, is there any implementation difference between the volatile and non-volatile member functions in the atomic classes? In other words, is there any need for the non-volatile overload?
I think that the volatile overloads exist for efficiency reasons. Volatile reads and writes are inherently more expensive than non-volatile reads and writes in C++0x, since the memory model puts some stringent requirements that prevent caching of values of volatile variables. If all the functions were only marked volatile, then the code couldn't necessarily make certain optimizations that would otherwise improve performance. Having the distinction allows the compiler to optimize non-volatile reads and writes when possible while degrading gracefully when volatile reads and writes are required.
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