Title
Deprecated free functions in <atomic>
Status
new
Section
[atomics.nonmembers]
Submitter
Alisdair Meredith

Created on 2020-03-19.00:00:00 last changed 5 months ago

Messages

Date: 2020-04-25.11:17:12

Proposed resolution:

This wording is relative to N4861.

  1. Modify [atomics.nonmembers] as indicated:

    -1- A non-member function template whose name matches the pattern atomic_f or the pattern atomic_f_explicit invokes the member function f, with the value of the first parameter as the object expression and the values of the remaining parameters (if any) as the arguments of the member function call, in order. An argument for a parameter of type atomic<T>::value_type* is dereferenced when passed to the member function call. If no such member function exists, the program is ill-formed. Otherwise, a call to such a function template has effects equivalent to ([structure.specifications]) the effective code sequence containing the f invocation specified in this subclause.

  2. Modify [depr.atomics.volatile], annex D, as indicated:

    If an atomic specialization has one of the following overloads, then that overload participates in overload resolution even if atomic<T>::is_always_lock_free is false:

    void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
    […]
    T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
    

    In addition, the following non-member function templates participate in overload resolution even if atomic<T>::is_always_lock_free is false:

    template<class T>
      void atomic_store(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
    template<class T>
      T atomic_load(const volatile atomic<T>*) noexcept;
    template<class T>
      T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
    template<class T>
      T atomic_exchange(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;
    template<class T>
    T atomic_exchange_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
      memory_order) noexcept;
    template<class T>
      bool atomic_compare_exchange_weak(volatile atomic<T>*,
                                        typename atomic<T>::value_type*,
                                        typename atomic<T>::value_type) noexcept;
    template<class T>
      bool atomic_compare_exchange_strong(volatile atomic<T>*,
                                          typename atomic<T>::value_type*,
                                          typename atomic<T>::value_type) noexcept;
    template<class T>
      bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
                                                 typename atomic<T>::value_type*,
                                                 typename atomic<T>::value_type,
                                                 memory_order, memory_order) noexcept;    
    template<class T>
      bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
                                                   typename atomic<T>::value_type*,
                                                   typename atomic<T>::value_type,
                                                   memory_order, memory_order) noexcept;  
    template<class T>
      T atomic_fetch_key(volatile atomic<T>*, typename atomic<T>::difference_type) noexcept;  
    template<class T>
      T atomic_fetch_key_explicit(volatile atomic<T>*, typename atomic<T>::difference_type,
                                  memory_order) noexcept;  
    template<class T>
      T atomic_fetch_key(volatile atomic<T>*, typename atomic<T>::value_type) noexcept;  
    template<class T>
      T atomic_fetch_key_explicit(volatile atomic<T>*, typename atomic<T>::value_type,
                                  memory_order) noexcept;  
    template<class T>
      void atomic_wait(const volatile atomic<T>*, typename atomic<T>::value_type);
    template<class T>
      void atomic_wait_explicit(const volatile atomic<T>*, typename atomic<T>::value_type,
                                memory_order);
    template<class T>
      void atomic_notify_one(volatile atomic<T>*);
    template<class T>
      void atomic_notify_all(volatile atomic<T>*);
    
Date: 2020-04-25.00:00:00

[ 2020-04-25 Issue Prioritization ]

Priority to 3 after reflector discussion.

Date: 2020-03-15.00:00:00

[ 2020-03-30; Tim improves wording ]

Date: 2020-03-15.00:00:00

[ 2020-03-29; Daniel provides wording ]

The suggested wording changes for [atomics.nonmembers] attempts to make clear that any of the specification elements of the member function (including but not restricted to Constraints: elements) are also imposed on the corresponding non-member function template. According to [structure.specifications], the wording "the semantics of the code sequence are determined by the Constraints,[…], and Error conditions specified for the function invocations contained in the code sequence." should realize the wanted effect. The advantage of this more general wording form is that we don't need to to worry in case that in the future Constraints: elements of the member functions are modified.

Date: 2020-03-19.00:00:00

Paper P1831R1 deprecated the volatile-qualified member functions of std::atomic unless is_always_lock_free is true. [atomics.nonmembers] maps free functions calls, declared in the <atomic> header, to those member functions, but does not deprecate them under the same circumstances.

I have confirmed with the paper author that the intended design was to deprecate these too, but currently we have no wording.

History
Date User Action Args
2020-04-25 11:17:12adminsetmessages: + msg11231
2020-03-30 15:29:10adminsetmessages: + msg11180
2020-03-29 13:50:27adminsetmessages: + msg11175
2020-03-29 13:50:27adminsetmessages: + msg11174
2020-03-19 00:00:00admincreate