diff --git a/build/aclocal/atomic_builtins.m4 b/build/aclocal/atomic_builtins.m4 index eac5d3336a..6ebc2279af 100644 --- a/build/aclocal/atomic_builtins.m4 +++ b/build/aclocal/atomic_builtins.m4 @@ -6,16 +6,13 @@ AC_DEFUN([WX_ATOMIC_BUILTINS], [ AC_REQUIRE([AC_PROG_CC]) if test -n "$GCC"; then - AC_MSG_CHECKING([for __sync_fetch_and_add and __sync_sub_and_fetch builtins]) + AC_MSG_CHECKING([for __sync_xxx_and_fetch builtins]) AC_CACHE_VAL(wx_cv_cc_gcc_atomic_builtins, [ AC_TRY_LINK( [], [ unsigned int value=0; - /* wxAtomicInc doesn't use return value here */ - __sync_fetch_and_add(&value, 2); - __sync_sub_and_fetch(&value, 1); - /* but wxAtomicDec does, so mimic that: */ + volatile unsigned int r1 = __sync_add_and_fetch(&value, 2); volatile unsigned int r2 = __sync_sub_and_fetch(&value, 1); ], wx_cv_cc_gcc_atomic_builtins=yes, diff --git a/configure b/configure index 1f78571587..e3ba68438d 100755 --- a/configure +++ b/configure @@ -25145,8 +25145,8 @@ fi if test -n "$GCC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_fetch_and_add and __sync_sub_and_fetch builtins" >&5 -$as_echo_n "checking for __sync_fetch_and_add and __sync_sub_and_fetch builtins... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_xxx_and_fetch builtins" >&5 +$as_echo_n "checking for __sync_xxx_and_fetch builtins... " >&6; } if ${wx_cv_cc_gcc_atomic_builtins+:} false; then : $as_echo_n "(cached) " >&6 else @@ -25159,10 +25159,7 @@ main () { unsigned int value=0; - /* wxAtomicInc doesn't use return value here */ - __sync_fetch_and_add(&value, 2); - __sync_sub_and_fetch(&value, 1); - /* but wxAtomicDec does, so mimic that: */ + volatile unsigned int r1 = __sync_add_and_fetch(&value, 2); volatile unsigned int r2 = __sync_sub_and_fetch(&value, 1); ; diff --git a/include/wx/atomic.h b/include/wx/atomic.h index 25bd049834..5112623515 100644 --- a/include/wx/atomic.h +++ b/include/wx/atomic.h @@ -17,10 +17,7 @@ // get the value of wxUSE_THREADS configuration flag #include "wx/defs.h" -// constraints on the various functions: -// - wxAtomicDec must return a zero value if the value is zero once -// decremented else it must return any non-zero value (the true value is OK -// but not necessary). +// these functions return the new value, after the operation #if wxUSE_THREADS @@ -31,9 +28,9 @@ // http://bugs.mysql.com/bug.php?id=28456 // http://golubenco.org/blog/atomic-operations/ -inline void wxAtomicInc (wxUint32 &value) +inline wxUint32 wxAtomicInc (wxUint32 &value) { - __sync_fetch_and_add(&value, 1); + return __sync_add_and_fetch(&value, 1); } inline wxUint32 wxAtomicDec (wxUint32 &value) @@ -47,9 +44,9 @@ inline wxUint32 wxAtomicDec (wxUint32 &value) // include standard Windows headers #include "wx/msw/wrapwin.h" -inline void wxAtomicInc (wxUint32 &value) +inline wxUint32 wxAtomicInc (wxUint32 &value) { - InterlockedIncrement ((LONG*)&value); + return InterlockedIncrement ((LONG*)&value); } inline wxUint32 wxAtomicDec (wxUint32 &value) @@ -60,9 +57,9 @@ inline wxUint32 wxAtomicDec (wxUint32 &value) #elif defined(__DARWIN__) #include "libkern/OSAtomic.h" -inline void wxAtomicInc (wxUint32 &value) +inline wxUint32 wxAtomicInc (wxUint32 &value) { - OSAtomicIncrement32 ((int32_t*)&value); + return OSAtomicIncrement32 ((int32_t*)&value); } inline wxUint32 wxAtomicDec (wxUint32 &value) @@ -76,7 +73,7 @@ inline wxUint32 wxAtomicDec (wxUint32 &value) inline void wxAtomicInc (wxUint32 &value) { - atomic_add_32 ((uint32_t*)&value, 1); + return atomic_add_32_nv ((uint32_t*)&value, 1); } inline wxUint32 wxAtomicDec (wxUint32 &value) @@ -94,7 +91,7 @@ inline wxUint32 wxAtomicDec (wxUint32 &value) #else // else of wxUSE_THREADS // if no threads are used we can safely use simple ++/-- -inline void wxAtomicInc (wxUint32 &value) { ++value; } +inline wxUint32 wxAtomicInc (wxUint32 &value) { return ++value; } inline wxUint32 wxAtomicDec (wxUint32 &value) { return --value; } #endif // !wxUSE_THREADS @@ -120,10 +117,10 @@ public: wxAtomicInt32& operator=(wxInt32 v) { m_value = v; return *this; } - void Inc() + wxInt32 Inc() { wxCriticalSectionLocker lock(m_locker); - ++m_value; + return ++m_value; } wxInt32 Dec() @@ -137,14 +134,14 @@ private: wxCriticalSection m_locker; }; -inline void wxAtomicInc(wxAtomicInt32 &value) { value.Inc(); } +inline wxInt32 wxAtomicInc(wxAtomicInt32 &value) { return value.Inc(); } inline wxInt32 wxAtomicDec(wxAtomicInt32 &value) { return value.Dec(); } #else // !wxNEEDS_GENERIC_ATOMIC_OPS #define wxHAS_ATOMIC_OPS -inline void wxAtomicInc(wxInt32 &value) { wxAtomicInc((wxUint32&)value); } +inline wxInt32 wxAtomicInc(wxInt32 &value) { return wxAtomicInc((wxUint32&)value); } inline wxInt32 wxAtomicDec(wxInt32 &value) { return wxAtomicDec((wxUint32&)value); } typedef wxInt32 wxAtomicInt32; diff --git a/interface/wx/atomic.h b/interface/wx/atomic.h index 441e6eb610..0eefd2d424 100644 --- a/interface/wx/atomic.h +++ b/interface/wx/atomic.h @@ -22,15 +22,18 @@ but is implemented in a generic way using a critical section which can be prohibitively expensive for use in performance-sensitive code. + Returns the new value after the increment (the return value is only + available since wxWidgets 3.1.7, this function doesn't return anything in + previous versions of the library). + @header{wx/atomic.h} */ -void wxAtomicInc(wxAtomicInt& value); +wxInt32 wxAtomicInc(wxAtomicInt& value); /** This function decrements value in an atomic manner. - Returns 0 if value is 0 after decrement or any non-zero value (not - necessarily equal to the value of the variable) otherwise. + Returns the new value after decrementing it. @see wxAtomicInc diff --git a/tests/thread/atomic.cpp b/tests/thread/atomic.cpp index 2d28ed475e..81c0672d7d 100644 --- a/tests/thread/atomic.cpp +++ b/tests/thread/atomic.cpp @@ -77,15 +77,14 @@ TEST_CASE("Atomic::NoThread", "[atomic]") CHECK( int2 == -ITERATIONS_NUM ); } -TEST_CASE("Atomic::DecReturn", "[atomic]") +TEST_CASE("Atomic::ReturnValue", "[atomic]") { wxAtomicInt i(0); - wxAtomicInc(i); - wxAtomicInc(i); - CHECK( i == 2 ); + REQUIRE( wxAtomicInc(i) == 1 ); + REQUIRE( wxAtomicInc(i) == 2 ); - CHECK( wxAtomicDec(i) > 0 ); - CHECK( wxAtomicDec(i) == 0 ); + REQUIRE( wxAtomicDec(i) == 1 ); + REQUIRE( wxAtomicDec(i) == 0 ); } TEST_CASE("Atomic::WithThreads", "[atomic]")