define wxHAS_ATOMIC_OPS only if native implementation is available; use fewer loop iterations in the test if it isn't as otherwise the test takes way too long to run

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53954 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-06-02 20:42:23 +00:00
parent f60ca3e24c
commit 42124e683d
4 changed files with 53 additions and 28 deletions

View File

@@ -188,6 +188,10 @@ the corresponding feature is available and not defined at all otherwise.
Currently the following symbols exist: Currently the following symbols exist:
@beginDefList @beginDefList
@itemdef{wxHAS_ATOMIC_OPS, Defined if wxAtomicInc() and wxAtomicDec() functions
have an efficient (CPU-specific) implementation. Notice that the functions
themselves are always available but can be prohibitively slow to use when
implemented in a generic way, using a critical section.}
@itemdef{wxHAS_LARGE_FILES, Defined if wxFile supports files more than 4GB in size.} @itemdef{wxHAS_LARGE_FILES, Defined if wxFile supports files more than 4GB in size.}
@itemdef{wxHAS_LARGE_FFILES, Defined if wxFFile supports files more than 4GB in size.} @itemdef{wxHAS_LARGE_FFILES, Defined if wxFFile supports files more than 4GB in size.}
@itemdef{wxHAS_POWER_EVENTS, Defined if wxPowerEvent are ever generated on the current platform.} @itemdef{wxHAS_POWER_EVENTS, Defined if wxPowerEvent are ever generated on the current platform.}

View File

@@ -88,7 +88,7 @@ inline wxUint32 wxAtomicDec (wxUint32 &value)
#else // unknown platform #else // unknown platform
// it will result in inclusion if the generic implementation code a bit later in this page // it will result in inclusion if the generic implementation code a bit later in this page
#define wxHAS_GENERIC_ATOMIC_OPS 1 #define wxNEEDS_GENERIC_ATOMIC_OPS
#endif // unknown platform #endif // unknown platform
@@ -105,11 +105,8 @@ inline wxUint32 wxAtomicDec (wxUint32 &value) { return --value; }
// behaviour // behaviour
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if !defined(wxHAS_GENERIC_ATOMIC_OPS) #ifdef wxNEEDS_GENERIC_ATOMIC_OPS
#define wxHAS_GENERIC_ATOMIC_OPS 0
#endif
#if wxHAS_GENERIC_ATOMIC_OPS
#include "wx/thread.h" // for wxCriticalSection #include "wx/thread.h" // for wxCriticalSection
class wxAtomicInt32 class wxAtomicInt32
@@ -144,14 +141,16 @@ private:
inline void wxAtomicInc(wxAtomicInt32 &value) { value.Inc(); } inline void wxAtomicInc(wxAtomicInt32 &value) { value.Inc(); }
inline wxInt32 wxAtomicDec(wxAtomicInt32 &value) { return value.Dec(); } inline wxInt32 wxAtomicDec(wxAtomicInt32 &value) { return value.Dec(); }
#else // !wxHAS_GENERIC_ATOMIC_OPS #else // !wxNEEDS_GENERIC_ATOMIC_OPS
#define wxHAS_ATOMIC_OPS
inline void wxAtomicInc(wxInt32 &value) { wxAtomicInc((wxUint32&)value); } inline void wxAtomicInc(wxInt32 &value) { wxAtomicInc((wxUint32&)value); }
inline wxInt32 wxAtomicDec(wxInt32 &value) { return wxAtomicDec((wxUint32&)value); } inline wxInt32 wxAtomicDec(wxInt32 &value) { return wxAtomicDec((wxUint32&)value); }
typedef wxInt32 wxAtomicInt32; typedef wxInt32 wxAtomicInt32;
#endif // wxHAS_GENERIC_ATOMIC_OPS #endif // wxNEEDS_GENERIC_ATOMIC_OPS
// all the native implementations use 32 bits currently // all the native implementations use 32 bits currently
// for a 64 bits implementation we could use (a future) wxAtomicInt64 as // for a 64 bits implementation we could use (a future) wxAtomicInt64 as

View File

@@ -17,14 +17,23 @@
/** /**
This function increments @a value in an atomic manner. This function increments @a value in an atomic manner.
Whenever possible wxWidgets provides an efficient, CPU-specific,
implementation of this function. If such implementation is available, the
symbol wxHAS_ATOMIC_OPS is defined. Otherwise this function still exists
but is implemented in a generic way using a critical section which can be
prohibitively expensive for use in performance-sensitive code.
@header{wx/atomic.h} @header{wx/atomic.h}
*/ */
void wxAtomicInc(wxAtomicInt& value); void wxAtomicInc(wxAtomicInt& value);
/** /**
This function decrements value in an atomic manner. Returns 0 if value is 0 This function decrements value in an atomic manner.
after decrementation or any non-zero value (not necessarily equal to the
value of the variable) otherwise. Returns 0 if value is 0 after decrement or any non-zero value (not
necessarily equal to the value of the variable) otherwise.
@see wxAtomicInc
@header{wx/atomic.h} @header{wx/atomic.h}
*/ */

View File

@@ -27,6 +27,18 @@
WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread); WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// number of times to run the loops: the code takes too long to run if we use
// the bigger value with generic atomic operations implementation
#ifdef wxHAS_ATOMIC_OPS
static const wxInt32 ITERATIONS_NUM = 10000000;
#else
static const wxInt32 ITERATIONS_NUM = 1000;
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// test class // test class
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -86,16 +98,17 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AtomicTestCase, "AtomicTestCase" );
void AtomicTestCase::TestNoThread() void AtomicTestCase::TestNoThread()
{ {
wxAtomicInt int1=0, int2=0; wxAtomicInt int1 = 0,
int2 = 0;
for (wxInt32 i=0; i<10000000; ++i) for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
{ {
wxAtomicInc(int1); wxAtomicInc(int1);
wxAtomicDec(int2); wxAtomicDec(int2);
} }
CPPUNIT_ASSERT( int1 == 10000000 ); CPPUNIT_ASSERT( int1 == ITERATIONS_NUM );
CPPUNIT_ASSERT( int2 == -10000000 ); CPPUNIT_ASSERT( int2 == -ITERATIONS_NUM );
} }
void AtomicTestCase::TestDecReturn() void AtomicTestCase::TestDecReturn()
@@ -160,25 +173,25 @@ void *AtomicTestCase::MyThread::Entry()
{ {
wxInt32 negativeValuesSeen = 0; wxInt32 negativeValuesSeen = 0;
for (wxInt32 i=0; i<10000000; ++i) for ( wxInt32 i = 0; i < ITERATIONS_NUM; ++i )
{ {
switch (m_testType) switch ( m_testType )
{ {
case AtomicTestCase::IncAndDecMixed: case AtomicTestCase::IncAndDecMixed:
wxAtomicInc(m_operateOn); wxAtomicInc(m_operateOn);
wxAtomicDec(m_operateOn); wxAtomicDec(m_operateOn);
if (m_operateOn < 0) if (m_operateOn < 0)
++negativeValuesSeen; ++negativeValuesSeen;
break; break;
case AtomicTestCase::IncOnly: case AtomicTestCase::IncOnly:
wxAtomicInc(m_operateOn); wxAtomicInc(m_operateOn);
break; break;
case AtomicTestCase::DecOnly: case AtomicTestCase::DecOnly:
wxAtomicDec(m_operateOn); wxAtomicDec(m_operateOn);
break; break;
} }
} }