// Purpose: functions to manipulate atomically integers and pointers
// Author: Armel Asselin
// Created: 12/13/2006
-// RCS-ID: $Id$
// Copyright: (c) Armel Asselin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#if wxUSE_THREADS
-#if defined(__WXMSW__)
+#if defined(HAVE_GCC_ATOMIC_BUILTINS)
-// include standard Windows headers
-#include "wx/msw/wrapwin.h"
+// NB: we intentionally don't use Linux's asm/atomic.h header, because it's
+// an internal kernel header that doesn't always work in userspace:
+// http://bugs.mysql.com/bug.php?id=28456
+// http://golubenco.org/blog/atomic-operations/
inline void wxAtomicInc (wxUint32 &value)
{
- InterlockedIncrement ((LONG*)&value);
+ __sync_fetch_and_add(&value, 1);
}
inline wxUint32 wxAtomicDec (wxUint32 &value)
{
- return InterlockedDecrement ((LONG*)&value);
+ return __sync_sub_and_fetch(&value, 1);
}
-#elif defined(__WXMAC__) || defined(__DARWIN__)
-#include "libkern/OSAtomic.h"
+#elif defined(__WINDOWS__)
+
+// include standard Windows headers
+#include "wx/msw/wrapwin.h"
+
inline void wxAtomicInc (wxUint32 &value)
{
- OSAtomicIncrement32 ((int32_t*)&value);
+ InterlockedIncrement ((LONG*)&value);
}
inline wxUint32 wxAtomicDec (wxUint32 &value)
{
- return OSAtomicDecrement32 ((int32_t*)&value);
+ return InterlockedDecrement ((LONG*)&value);
}
-#elif defined(__LINUX__)
-
-#include <asm/atomic.h>
+#elif defined(__WXMAC__) || defined(__DARWIN__)
+#include "libkern/OSAtomic.h"
inline void wxAtomicInc (wxUint32 &value)
{
- atomic_inc ((atomic_t*)&value);
+ OSAtomicIncrement32 ((int32_t*)&value);
}
inline wxUint32 wxAtomicDec (wxUint32 &value)
{
- return atomic_dec_and_test ((atomic_t*)&value) ? 0 : 1;
+ return OSAtomicDecrement32 ((int32_t*)&value);
}
#elif defined (__SOLARIS__)
#else // unknown platform
// 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
// behaviour
// ----------------------------------------------------------------------------
-#if !defined(wxHAS_GENERIC_ATOMIC_OPS)
-#define wxHAS_GENERIC_ATOMIC_OPS 0
-#endif
+#ifdef wxNEEDS_GENERIC_ATOMIC_OPS
-#if wxHAS_GENERIC_ATOMIC_OPS
#include "wx/thread.h" // for wxCriticalSection
class wxAtomicInt32
{
public:
- wxAtomicInt() { } // non initialized for consistency with basic int type
- wxAtomicInt(wxInt32 v) : m_value(v) { }
+ wxAtomicInt32() { } // non initialized for consistency with basic int type
+ wxAtomicInt32(wxInt32 v) : m_value(v) { }
+ wxAtomicInt32(const wxAtomicInt32& a) : m_value(a.m_value) {}
operator wxInt32() const { return m_value; }
- operator wxInt32&() { return m_value; }
+ operator volatile wxInt32&() { return m_value; }
- wxAtomicInt& operator=(wxInt32 v) { m_value = v; return *this; }
+ wxAtomicInt32& operator=(wxInt32 v) { m_value = v; return *this; }
void Inc()
{
wxCriticalSection m_locker;
};
-inline void wxAtomicInc(wxAtomicInt &value) { value.Inc(); }
-inline wxInt32 wxAtomicDec(wxAtomicInt &value) { return value.Dec(); }
+inline void wxAtomicInc(wxAtomicInt32 &value) { value.Inc(); }
+inline wxInt32 wxAtomicDec(wxAtomicInt32 &value) { return value.Dec(); }
+
+#else // !wxNEEDS_GENERIC_ATOMIC_OPS
-#else // !wxHAS_GENERIC_ATOMIC_OPS
+#define wxHAS_ATOMIC_OPS
inline void wxAtomicInc(wxInt32 &value) { wxAtomicInc((wxUint32&)value); }
inline wxInt32 wxAtomicDec(wxInt32 &value) { return wxAtomicDec((wxUint32&)value); }
typedef wxInt32 wxAtomicInt32;
-#endif // wxHAS_GENERIC_ATOMIC_OPS
+#endif // wxNEEDS_GENERIC_ATOMIC_OPS
// all the native implementations use 32 bits currently
// for a 64 bits implementation we could use (a future) wxAtomicInt64 as