/* A stand-in <atomic> as libstdc++ shipped it before P0558R1 (GCC 8
 * and earlier): the free functions deduce their value parameter from
 * the argument as well as from the pointer, so passing an enumerator
 * or any type but the atomic's own fails to deduce.  Only the parts
 * retro_atomic.h's C++11 backend uses are declared; nothing is
 * defined, the test only compiles against it. */
#ifndef RETRO_ATOMIC_OLD_STL_ATOMIC
#define RETRO_ATOMIC_OLD_STL_ATOMIC

namespace std
{
   typedef enum memory_order
   {
      memory_order_relaxed,
      memory_order_consume,
      memory_order_acquire,
      memory_order_release,
      memory_order_acq_rel,
      memory_order_seq_cst
   } memory_order;

   template<typename _Tp>
   struct atomic
   {
      _Tp _M_i;

      atomic() { }
      atomic(_Tp __i) : _M_i(__i) { }

      void store(_Tp __i, memory_order __m = memory_order_seq_cst);
      _Tp  load(memory_order __m = memory_order_seq_cst) const;
      _Tp  exchange(_Tp __i, memory_order __m = memory_order_seq_cst);
      bool compare_exchange_strong(_Tp& __e, _Tp __i,
            memory_order __s, memory_order __f);
   };

   template<typename _ITp>
   void atomic_init(atomic<_ITp>* __a, _ITp __i);

   template<typename _ITp>
   void atomic_store_explicit(atomic<_ITp>* __a, _ITp __i, memory_order __m);

   template<typename _ITp>
   _ITp atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m);

   template<typename _ITp>
   _ITp atomic_fetch_add_explicit(atomic<_ITp>* __a, _ITp __i, memory_order __m);

   template<typename _ITp>
   _ITp atomic_fetch_sub_explicit(atomic<_ITp>* __a, _ITp __i, memory_order __m);

   template<typename _ITp>
   _ITp atomic_fetch_or_explicit(atomic<_ITp>* __a, _ITp __i, memory_order __m);

   template<typename _ITp>
   _ITp atomic_fetch_and_explicit(atomic<_ITp>* __a, _ITp __i, memory_order __m);

   void atomic_thread_fence(memory_order __m);
}

#endif
