Return the new value from wxAtomicInc() too

This is easy to do and can be useful when using an atomic initialization
counter.

The only platform where not returning the new value might be more
efficient than returning it is Solaris which is not really relevant any
more and on all the other platforms the functions we were already using
provided this value already (or almost, in case of using gcc builtins,
when we just have to use a different one).
This commit is contained in:
Vadim Zeitlin 2022-05-11 00:12:43 +02:00
parent e82290f0da
commit cf66ce5f94
5 changed files with 29 additions and 36 deletions

View File

@ -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,

9
configure vendored
View File

@ -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);
;

View File

@ -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;

View File

@ -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

View File

@ -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]")