diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index a6ddea3..cc44ac2 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -31,13 +31,12 @@ // ++a; // // Effects: Atomically increments the value of a -// Returns: nothing +// Returns: (long) the new value of a // // --a; // // Effects: Atomically decrements the value of a -// Returns: (long) zero if the new value of a is zero, -// unspecified non-zero value otherwise (usually the new value) +// Returns: (long) the new value of a // // Important note: when --a returns zero, it must act as a // read memory barrier (RMB); i.e. the calling thread must diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 1305632..54807e9 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -40,21 +40,21 @@ class atomic_count { public: - explicit atomic_count(long v) : value_(v) {} + explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __atomic_add(&value_, 1); + return __exchange_and_add( &value_, +1 ) + 1; } long operator--() { - return __exchange_and_add(&value_, -1) - 1; + return __exchange_and_add( &value_, -1 ) - 1; } operator long() const { - return __exchange_and_add(&value_, 0); + return __exchange_and_add( &value_, 0 ); } private: diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 4fd1c57..5c44d7c 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -25,16 +25,9 @@ public: explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} - void operator++() + long operator++() { - __asm__ - ( - "lock\n\t" - "incl %0": - "+m"( value_ ): // output (%0) - : // inputs - "cc" // clobbers - ); + return atomic_exchange_and_add( &value_, +1 ) + 1; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index d8118f0..05f7867 100644 --- a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -62,10 +62,10 @@ public: pthread_mutex_destroy(&mutex_); } - void operator++() + long operator++() { scoped_lock lock(mutex_); - ++value_; + return ++value_; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp index f2d22fb..b6359b5 100644 --- a/include/boost/smart_ptr/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -31,9 +31,9 @@ public: explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __sync_add_and_fetch( &value_, 1 ); + return __sync_add_and_fetch( &value_, 1 ); } long operator--() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 07f0840..f52d641 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -58,5 +58,6 @@ import testing ; [ run sp_recursive_assign2_rv_test.cpp ] [ run esft_constructor_test.cpp ] [ compile-fail auto_ptr_lv_fail.cpp ] + [ run atomic_count_test2.cpp ] ; } diff --git a/test/atomic_count_test2.cpp b/test/atomic_count_test2.cpp new file mode 100644 index 0000000..7e6dd97 --- /dev/null +++ b/test/atomic_count_test2.cpp @@ -0,0 +1,55 @@ +// +// atomic_count_test2.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +int main() +{ + boost::detail::atomic_count n( 4 ); + + BOOST_TEST( n == 4 ); + + BOOST_TEST( ++n == 5 ); + BOOST_TEST( ++n == 6 ); + + BOOST_TEST( n == 6 ); + + BOOST_TEST( --n == 5 ); + BOOST_TEST( --n == 4 ); + + BOOST_TEST( n == 4 ); + + boost::detail::atomic_count m( 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( ++m == 1 ); + BOOST_TEST( ++m == 2 ); + + BOOST_TEST( m == 2 ); + + BOOST_TEST( --m == 1 ); + BOOST_TEST( --m == 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( --m == -1 ); + BOOST_TEST( --m == -2 ); + + BOOST_TEST( m == -2 ); + + BOOST_TEST( ++m == -1 ); + BOOST_TEST( ++m == 0 ); + + BOOST_TEST( m == 0 ); + + return boost::report_errors(); +}