diff mbox

Unifying std::atomic_int and std::atomic<int>

Message ID 20141024141428.GD3033@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 24, 2014, 2:14 p.m. UTC
Our <atomic> was implemented (by Benjamin IIRC) based on an early
C++0x draft when the spec was still trying to be valid for both C and
C++. Part of the C compatibility aspect was that std::atomic_int is
allowed to be either a typedef for std::atomic<int> or a base class of
it, so that a C library could define std::atomic_int and then the C++
library could make std::atomic<int> derive from that.

In the final C11 spec atomics work completely differently, and
atomic_int is a typedef for _Atomic int, which is not a valid base
class. So the old C++0x draft's compatibility aim is impossible,
atomic_int can never be the same type in C and C++.

In our implementation, std::atomic_int is a base class of
std::atomic<int>, which has no benefit I can see, but causes
https://gcc.gnu.org/PR60940

Rather than overloading every atomic_op() non-member function to
handle the derived class and the base class, it would be simpler to
just get rid of the base classes and make atomic_xxx a typedef for
atomic<xxx>, as the attached patch does for atomic_{bool,char,schar}.

Does anyone object to that change?

If you object, are you prepared to do the work to fix PR60940? :-)



[Note:- it could probably be simplified even further so atomic<char>
is just:

  template<>
    struct atomic<char> : public __atomic_base<char>
    {
      using __atomic_base<char>::__atomic_base;
    };

But that could be done later as it wouldn't change anything
observable, making atomic_char a typedef for atomic<char> is the
observable and IMHO important change. -end note]
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 1fc0ebb..a591c46 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -120,12 +120,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _IntTp>
     struct __atomic_base;
 
-  /// atomic_char
-  typedef __atomic_base<char>  	       		atomic_char;
-
-  /// atomic_schar
-  typedef __atomic_base<signed char>	     	atomic_schar;
-
   /// atomic_uchar
   typedef __atomic_base<unsigned char>		atomic_uchar;
 
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index 85dc252..c58853e 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -49,21 +49,25 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @{
    */
 
-  /// atomic_bool
+  template<typename _Tp>
+    struct atomic;
+
+  /// atomic<bool>
   // NB: No operators or fetch-operations for this type.
-  struct atomic_bool
+  template<>
+  struct atomic<bool>
   {
   private:
     __atomic_base<bool>	_M_base;
 
   public:
-    atomic_bool() noexcept = default;
-    ~atomic_bool() noexcept = default;
-    atomic_bool(const atomic_bool&) = delete;
-    atomic_bool& operator=(const atomic_bool&) = delete;
-    atomic_bool& operator=(const atomic_bool&) volatile = delete;
+    atomic() noexcept = default;
+    ~atomic() noexcept = default;
+    atomic(const atomic&) = delete;
+    atomic& operator=(const atomic&) = delete;
+    atomic& operator=(const atomic&) volatile = delete;
 
-    constexpr atomic_bool(bool __i) noexcept : _M_base(__i) { }
+    constexpr atomic(bool __i) noexcept : _M_base(__i) { }
 
     bool
     operator=(bool __i) noexcept
@@ -151,6 +155,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
   };
 
+  /// atomic_bool
+  typedef atomic<bool> atomic_bool;
+
 
   /**
    *  @brief Generic atomic type, primary class template.
@@ -485,31 +492,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
 
-  /// Explicit specialization for bool.
-  template<>
-    struct atomic<bool> : public atomic_bool
-    {
-      typedef bool 			__integral_type;
-      typedef atomic_bool 		__base_type;
-
-      atomic() noexcept = default;
-      ~atomic() noexcept = default;
-      atomic(const atomic&) = delete;
-      atomic& operator=(const atomic&) = delete;
-      atomic& operator=(const atomic&) volatile = delete;
-
-      constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
-
-      using __base_type::operator __integral_type;
-      using __base_type::operator=;
-    };
-
   /// Explicit specialization for char.
   template<>
-    struct atomic<char> : public atomic_char
+    struct atomic<char> : public __atomic_base<char>
     {
       typedef char 			__integral_type;
-      typedef atomic_char 		__base_type;
+      typedef __atomic_base<char> 	__base_type;
 
       atomic() noexcept = default;
       ~atomic() noexcept = default;
@@ -523,12 +511,15 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __base_type::operator=;
     };
 
+  /// atomic_char
+  typedef atomic<char>  	       		atomic_char;
+
   /// Explicit specialization for signed char.
   template<>
-    struct atomic<signed char> : public atomic_schar
+    struct atomic<signed char> : public __atomic_base<signed char>
     {
       typedef signed char 		__integral_type;
-      typedef atomic_schar 		__base_type;
+      typedef __atomic_base<signed char> 	__base_type;
 
       atomic() noexcept= default;
       ~atomic() noexcept = default;
@@ -542,6 +533,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __base_type::operator=;
     };
 
+  /// atomic_schar
+  typedef atomic<signed char>  	       		atomic_schar;
+
   /// Explicit specialization for unsigned char.
   template<>
     struct atomic<unsigned char> : public atomic_uchar