Title
Non-volatile atomic functions
Status
resolved
Section
[atomics.types.operations]
Submitter
Jeffrey Yasskin

Created on 2009-06-16.00:00:00 last changed 169 months ago

Messages

Date: 2010-12-05.14:14:49

[ 2009-10 Santa Cruz: ]

NAD EditorialResolved. Addressed by N2992.

Date: 2009-06-16.00:00:00

[ 2009-06-16 Lawrence adds: ]

I recommend allowing non-volatile overloads.

Date: 2009-06-16.00:00:00

Addresses US 90

The C++0X draft declares all of the functions dealing with atomics (section [atomics.types.operations]) to take volatile arguments. Yet it also says (29.4-3),

[ Note: Many operations are volatile-qualified. The "volatile as device register" semantics have not changed in the standard. This qualification means that volatility is preserved when applying these operations to volatile objects. It does not mean that operations on non-volatile objects become volatile. Thus, volatile qualified operations on non-volatile objects may be merged under some conditions. — end note ]

I was thinking about how to implement this in gcc, and I believe that we'll want to overload most of the functions on volatile and non-volatile. Here's why:

To let the compiler take advantage of the permission to merge non-volatile atomic operations and reorder atomics in certain, we'll need to tell the compiler backend about exactly which atomic operation was used. So I expect most of the functions of the form atomic_<op>_explicit() (e.g. atomic_load_explicit, atomic_exchange_explicit, atomic_fetch_add_explicit, etc.) to become compiler builtins. A builtin can tell whether its argument was volatile or not, so those functions don't really need extra explicit overloads. However, I don't expect that we'll want to add builtins for every function in chapter 29, since most can be implemented in terms of the _explicit free functions:

class atomic_int {
  __atomic_int_storage value;
 public:
  int fetch_add(int increment, memory_order order = memory_order_seq_cst) volatile {
    // &value has type "volatile __atomic_int_storage*".
    atomic_fetch_add_explicit(&value, increment, order);
  }
  ...
};

But now this always calls the volatile builtin version of atomic_fetch_add_explicit(), even if the atomic_int wasn't declared volatile. To preserve volatility and the compiler's permission to optimize, I'd need to write:

class atomic_int {
  __atomic_int_storage value;
 public:
  int fetch_add(int increment, memory_order order = memory_order_seq_cst) volatile {
    atomic_fetch_add_explicit(&value, increment, order);
  }
  int fetch_add(int increment, memory_order order = memory_order_seq_cst) {
    atomic_fetch_add_explicit(&value, increment, order);
  }
  ...
};

But this is visibly different from the declarations in the standard because it's now overloaded. (Consider passing &atomic_int::fetch_add as a template parameter.)

The implementation may already have permission to add overloads to the member functions:

[member.functions] An implementation may declare additional non-virtual member function signatures within a class:
...

  • by adding a member function signature for a member function name.

but I don't see an equivalent permission to add overloads to the free functions.

History
Date User Action Args
2010-12-05 14:14:49adminsetstatus: nad editorial -> resolved
2010-10-21 18:28:33adminsetmessages: + msg913
2010-10-21 18:28:33adminsetmessages: + msg912
2009-06-16 00:00:00admincreate