Boost logo

Boost-Commit :

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;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk