$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84190 - in trunk: boost/atomic/detail libs/atomic/test
From: tim_at_[hidden]
Date: 2013-05-08 00:45:40
Author: timblechmann
Date: 2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
New Revision: 84190
URL: http://svn.boost.org/trac/boost/changeset/84190
Log:
atomic: provide additive functionality for atomic<void*>
fixes #8501
Text files modified: 
   trunk/boost/atomic/detail/base.hpp          |    67 +++++++++++++++++++++++++++++++++       
   trunk/boost/atomic/detail/cas32strong.hpp   |     6 +-                                      
   trunk/boost/atomic/detail/cas32weak.hpp     |    20 +++++++++                               
   trunk/boost/atomic/detail/cas64strong.hpp   |     6 +-                                      
   trunk/boost/atomic/detail/gcc-ppc.hpp       |    78 ++++++++++++++++++++++++++++++++++++++- 
   trunk/boost/atomic/detail/gcc-sparcv9.hpp   |    20 +++++++++                               
   trunk/boost/atomic/detail/gcc-x86.hpp       |    42 ++++++++++++++++++++-                   
   trunk/boost/atomic/detail/windows.hpp       |    18 ++++++++                                
   trunk/libs/atomic/test/api_test_helpers.hpp |    35 ++++++++++-------                       
   9 files changed, 264 insertions(+), 28 deletions(-)
Modified: trunk/boost/atomic/detail/base.hpp
==============================================================================
--- trunk/boost/atomic/detail/base.hpp	(original)
+++ trunk/boost/atomic/detail/base.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -79,6 +79,43 @@
         return fetch_sub(v) - v; \
     } \
 
+#define BOOST_ATOMIC_DECLARE_VOID_POINTER_ADDITIVE_OPERATORS \
+    value_type \
+    operator++(int) volatile BOOST_NOEXCEPT \
+    { \
+        return fetch_add(1); \
+    } \
+     \
+    value_type \
+    operator++(void) volatile BOOST_NOEXCEPT \
+    { \
+        return (char*)fetch_add(1) + 1;         \
+    } \
+     \
+    value_type \
+    operator--(int) volatile BOOST_NOEXCEPT \
+    { \
+        return fetch_sub(1); \
+    } \
+     \
+    value_type \
+    operator--(void) volatile BOOST_NOEXCEPT \
+    { \
+        return (char*)fetch_sub(1) - 1;         \
+    } \
+     \
+    value_type \
+    operator+=(difference_type v) volatile BOOST_NOEXCEPT \
+    { \
+        return (char*)fetch_add(v) + v; \
+    } \
+     \
+    value_type \
+    operator-=(difference_type v) volatile BOOST_NOEXCEPT \
+    { \
+        return (char*)fetch_sub(v) - v; \
+    } \
+
 #define BOOST_ATOMIC_DECLARE_BIT_OPERATORS \
     value_type \
     operator&=(difference_type v) volatile BOOST_NOEXCEPT \
@@ -102,6 +139,10 @@
     BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
     BOOST_ATOMIC_DECLARE_ADDITIVE_OPERATORS \
 
+#define BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS \
+    BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_ADDITIVE_OPERATORS \
+
 #define BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS \
     BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
     BOOST_ATOMIC_DECLARE_ADDITIVE_OPERATORS \
@@ -444,6 +485,7 @@
 {
 private:
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
     typedef lockpool::scoped_lock guard_type;
 public:
@@ -506,7 +548,30 @@
         return false;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type fetch_add(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        guard_type guard(const_cast<value_type *>(&v_));
+
+        value_type old = v_;
+        char * cv = reinterpret_cast<char*>(old);
+        cv += v;
+        v_ = cv;
+        return old;
+    }
+
+    value_type fetch_sub(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
+    {
+        guard_type guard(const_cast<value_type *>(&v_));
+
+        value_type old = v_;
+        char * cv = reinterpret_cast<char*>(old);
+        cv -= v;
+        v_ = cv;
+        return old;
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
+
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/cas32strong.hpp
==============================================================================
--- trunk/boost/atomic/detail/cas32strong.hpp	(original)
+++ trunk/boost/atomic/detail/cas32strong.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -479,7 +479,7 @@
     {
         value_type original = load(memory_order_relaxed);
         do {
-        } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
+        } while (!compare_exchange_weak(original, (char*)original + v, order, memory_order_relaxed));
         return original;
     }
 
@@ -488,7 +488,7 @@
     {
         value_type original = load(memory_order_relaxed);
         do {
-        } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
+        } while (!compare_exchange_weak(original, (char*)original - v, order, memory_order_relaxed));
         return original;
     }
 
@@ -498,7 +498,7 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/cas32weak.hpp
==============================================================================
--- trunk/boost/atomic/detail/cas32weak.hpp	(original)
+++ trunk/boost/atomic/detail/cas32weak.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -509,7 +509,25 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original = load(memory_order_relaxed);
+        do {
+        } while (!compare_exchange_weak(original, (char*)original + v, order, memory_order_relaxed));
+        return original;
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original = load(memory_order_relaxed);
+        do {
+        } while (!compare_exchange_weak(original, (char*)original - v, order, memory_order_relaxed));
+        return original;
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/cas64strong.hpp
==============================================================================
--- trunk/boost/atomic/detail/cas64strong.hpp	(original)
+++ trunk/boost/atomic/detail/cas64strong.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -223,7 +223,7 @@
     {
         value_type original = load(memory_order_relaxed);
         do {
-        } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
+        } while (!compare_exchange_weak(original, (char*)original + v, order, memory_order_relaxed));
         return original;
     }
 
@@ -232,7 +232,7 @@
     {
         value_type original = load(memory_order_relaxed);
         do {
-        } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
+        } while (!compare_exchange_weak(original, (char*)original - v, order, memory_order_relaxed));
         return original;
     }
 
@@ -242,7 +242,7 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/gcc-ppc.hpp
==============================================================================
--- trunk/boost/atomic/detail/gcc-ppc.hpp	(original)
+++ trunk/boost/atomic/detail/gcc-ppc.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -1525,6 +1525,7 @@
 class base_atomic<void *, void *, 4, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
@@ -1643,7 +1644,43 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original, tmp;
+        ppc_fence_before(order);
+        __asm__ (
+            "1:\n"
+            "lwarx %0,%y2\n"
+            "add %1,%0,%3\n"
+            "stwcx. %1,%y2\n"
+            "bne- 1b\n"
+            : "=&b" (original), "=&b" (tmp), "+Z"(v_)
+            : "b" (v)
+            : "cc");
+        ppc_fence_after(order);
+        return original;
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original, tmp;
+        ppc_fence_before(order);
+        __asm__ (
+            "1:\n"
+            "lwarx %0,%y2\n"
+            "sub %1,%0,%3\n"
+            "stwcx. %1,%y2\n"
+            "bne- 1b\n"
+            : "=&b" (original), "=&b" (tmp), "+Z"(v_)
+            : "b" (v)
+            : "cc");
+        ppc_fence_after(order);
+        return original;
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
@@ -1824,6 +1861,7 @@
 class base_atomic<void *, void *, 8, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
@@ -1942,7 +1980,43 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original, tmp;
+        ppc_fence_before(order);
+        __asm__ (
+            "1:\n"
+            "ldarx %0,%y2\n"
+            "add %1,%0,%3\n"
+            "stdcx. %1,%y2\n"
+            "bne- 1b\n"
+            : "=&b" (original), "=&b" (tmp), "+Z"(v_)
+            : "b" (v)
+            : "cc");
+        ppc_fence_after(order);
+        return original;
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type original, tmp;
+        ppc_fence_before(order);
+        __asm__ (
+            "1:\n"
+            "ldarx %0,%y2\n"
+            "sub %1,%0,%3\n"
+            "stdcx. %1,%y2\n"
+            "bne- 1b\n"
+            : "=&b" (original), "=&b" (tmp), "+Z"(v_)
+            : "b" (v)
+            : "cc");
+        ppc_fence_after(order);
+        return original;
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/gcc-sparcv9.hpp
==============================================================================
--- trunk/boost/atomic/detail/gcc-sparcv9.hpp	(original)
+++ trunk/boost/atomic/detail/gcc-sparcv9.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -792,6 +792,7 @@
 class base_atomic<void *, void *, 4, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
@@ -857,7 +858,24 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type tmp = load(memory_order_relaxed);
+        do {} while(!compare_exchange_weak(tmp, (char*)tmp + v, order, memory_order_relaxed));
+        return tmp;
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        value_type tmp = load(memory_order_relaxed);
+        do {} while(!compare_exchange_weak(tmp, (char*)tmp - v, order, memory_order_relaxed));
+        return tmp;
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
+
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/gcc-x86.hpp
==============================================================================
--- trunk/boost/atomic/detail/gcc-x86.hpp	(original)
+++ trunk/boost/atomic/detail/gcc-x86.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -808,6 +808,7 @@
 class base_atomic<void *, void *, 4, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
@@ -875,7 +876,25 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        platform_fence_before(order);
+        __asm__ (
+        "lock ; xaddl %0, %1"
+        : "+r" (v), "+m" (v_)
+                );
+        platform_fence_after(order);
+        return reinterpret_cast<value_type>(v);
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        return fetch_add(-v, order);
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
@@ -994,6 +1013,7 @@
 class base_atomic<void *, void *, 8, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void * value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
@@ -1061,7 +1081,25 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        platform_fence_before(order);
+        __asm__ (
+            "lock ; xaddq %0, %1"
+            : "+r" (v), "+m" (v_)
+        );
+        platform_fence_after(order);
+        return reinterpret_cast<value_type>(v);
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        return fetch_add(-v, order);
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/boost/atomic/detail/windows.hpp
==============================================================================
--- trunk/boost/atomic/detail/windows.hpp	(original)
+++ trunk/boost/atomic/detail/windows.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -878,6 +878,7 @@
 class base_atomic<void*, void*, sizeof_pointer, Sign>
 {
     typedef base_atomic this_type;
+    typedef ptrdiff_t difference_type;
     typedef void* value_type;
 public:
     BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT: v_(v) {}
@@ -938,7 +939,22 @@
         return true;
     }
 
-    BOOST_ATOMIC_DECLARE_BASE_OPERATORS
+    value_type
+    fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        platform_fence_before(order);
+        value_type res = (value_type)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(&v_, v);
+        platform_fence_after(order);
+        return res;
+    }
+
+    value_type
+    fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
+    {
+        return fetch_add(-v, order);
+    }
+
+    BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
 private:
     base_atomic(const base_atomic &) /* = delete */ ;
     void operator=(const base_atomic &) /* = delete */ ;
Modified: trunk/libs/atomic/test/api_test_helpers.hpp
==============================================================================
--- trunk/libs/atomic/test/api_test_helpers.hpp	(original)
+++ trunk/libs/atomic/test/api_test_helpers.hpp	2013-05-08 00:45:38 EDT (Wed, 08 May 2013)
@@ -111,8 +111,8 @@
 #endif
 }
 
-template<typename T, typename D>
-void test_additive_operators(T value, D delta)
+template<typename T, typename D, typename AddType>
+void test_additive_operators_with_type(T value, D delta)
 {
     /* note: the tests explicitly cast the result of any addition
     to the type to be tested to force truncation of the result to
@@ -122,14 +122,14 @@
     {
         boost::atomic<T> a(value);
         T n = a.fetch_add(delta);
-        BOOST_CHECK( a.load() == T(value + delta) );
+        BOOST_CHECK( a.load() == T((AddType)value + delta) );
         BOOST_CHECK( n == value );
     }
 
     {
         boost::atomic<T> a(value);
         T n = a.fetch_sub(delta);
-        BOOST_CHECK( a.load() == T(value - delta) );
+        BOOST_CHECK( a.load() == T((AddType)value - delta) );
         BOOST_CHECK( n == value );
     }
 
@@ -137,47 +137,53 @@
     {
         boost::atomic<T> a(value);
         T n = (a += delta);
-        BOOST_CHECK( a.load() == T(value + delta) );
-        BOOST_CHECK( n == T(value + delta) );
+        BOOST_CHECK( a.load() == T((AddType)value + delta) );
+        BOOST_CHECK( n == T((AddType)value + delta) );
     }
 
     {
         boost::atomic<T> a(value);
         T n = (a -= delta);
-        BOOST_CHECK( a.load() == T(value - delta) );
-        BOOST_CHECK( n == T(value - delta) );
+        BOOST_CHECK( a.load() == T((AddType)value - delta) );
+        BOOST_CHECK( n == T((AddType)value - delta) );
     }
 
     /* overloaded increment/decrement */
     {
         boost::atomic<T> a(value);
         T n = a++;
-        BOOST_CHECK( a.load() == T(value + 1) );
+        BOOST_CHECK( a.load() == T((AddType)value + 1) );
         BOOST_CHECK( n == value );
     }
 
     {
         boost::atomic<T> a(value);
         T n = ++a;
-        BOOST_CHECK( a.load() == T(value + 1) );
-        BOOST_CHECK( n == T(value + 1) );
+        BOOST_CHECK( a.load() == T((AddType)value + 1) );
+        BOOST_CHECK( n == T((AddType)value + 1) );
     }
 
     {
         boost::atomic<T> a(value);
         T n = a--;
-        BOOST_CHECK( a.load() == T(value - 1) );
+        BOOST_CHECK( a.load() == T((AddType)value - 1) );
         BOOST_CHECK( n == value );
     }
 
     {
         boost::atomic<T> a(value);
         T n = --a;
-        BOOST_CHECK( a.load() == T(value - 1) );
-        BOOST_CHECK( n == T(value - 1) );
+        BOOST_CHECK( a.load() == T((AddType)value - 1) );
+        BOOST_CHECK( n == T((AddType)value - 1) );
     }
 }
 
+template<typename T, typename D>
+void test_additive_operators(T value, D delta)
+{
+    test_additive_operators_with_type<T, D, T>(value, delta);
+}
+
 template<typename T>
 void test_additive_wrap(T value)
 {
@@ -275,6 +281,7 @@
     test_additive_operators<T*>(&values[1], 1);
 
     test_base_operators<void*>(&values[0], &values[1], &values[2]);
+    test_additive_operators_with_type<void*, int, char*>(&values[1], 1);
 
     boost::atomic<void *> ptr;
     boost::atomic<intptr_t> integral;