1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: functions to manipulate atomically integers and pointers
4 // Author: Armel Asselin
7 // Copyright: (c) Armel Asselin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // get the value of wxUSE_THREADS configuration flag
21 // constraints on the various functions:
22 // - wxAtomicDec must return a zero value if the value is zero once
23 // decremented else it must return any non-zero value (the true value is OK
24 // but not necessary).
28 #if defined(HAVE_GCC_ATOMIC_BUILTINS)
30 // NB: we intentionally don't use Linux's asm/atomic.h header, because it's
31 // an internal kernel header that doesn't always work in userspace:
32 // http://bugs.mysql.com/bug.php?id=28456
33 // http://golubenco.org/blog/atomic-operations/
35 inline void wxAtomicInc (wxUint32
&value
)
37 __sync_fetch_and_add(&value
, 1);
40 inline wxUint32
wxAtomicDec (wxUint32
&value
)
42 return __sync_sub_and_fetch(&value
, 1);
46 #elif defined(__WXMSW__)
48 // include standard Windows headers
49 #include "wx/msw/wrapwin.h"
51 inline void wxAtomicInc (wxUint32
&value
)
53 InterlockedIncrement ((LONG
*)&value
);
56 inline wxUint32
wxAtomicDec (wxUint32
&value
)
58 return InterlockedDecrement ((LONG
*)&value
);
61 #elif defined(__WXMAC__) || defined(__DARWIN__)
63 #include "libkern/OSAtomic.h"
64 inline void wxAtomicInc (wxUint32
&value
)
66 OSAtomicIncrement32 ((int32_t*)&value
);
69 inline wxUint32
wxAtomicDec (wxUint32
&value
)
71 return OSAtomicDecrement32 ((int32_t*)&value
);
74 #elif defined (__SOLARIS__)
78 inline void wxAtomicInc (wxUint32
&value
)
80 atomic_add_32 ((uint32_t*)&value
, 1);
83 inline wxUint32
wxAtomicDec (wxUint32
&value
)
85 return atomic_add_32_nv ((uint32_t*)&value
, (uint32_t)-1);
88 #else // unknown platform
90 // it will result in inclusion if the generic implementation code a bit later in this page
91 #define wxHAS_GENERIC_ATOMIC_OPS 1
93 #endif // unknown platform
95 #else // else of wxUSE_THREADS
96 // if no threads are used we can safely use simple ++/--
98 inline void wxAtomicInc (wxUint32
&value
) { ++value
; }
99 inline wxUint32
wxAtomicDec (wxUint32
&value
) { return --value
; }
101 #endif // !wxUSE_THREADS
103 // ----------------------------------------------------------------------------
104 // proxies to actual implementations, but for various other types with same
106 // ----------------------------------------------------------------------------
108 #if !defined(wxHAS_GENERIC_ATOMIC_OPS)
109 #define wxHAS_GENERIC_ATOMIC_OPS 0
112 #if wxHAS_GENERIC_ATOMIC_OPS
113 #include "wx/thread.h" // for wxCriticalSection
118 wxAtomicInt32() { } // non initialized for consistency with basic int type
119 wxAtomicInt32(wxInt32 v
) : m_value(v
) { }
120 wxAtomicInt32(const wxAtomicInt32
& a
) : m_value(a
.m_value
) {}
122 operator wxInt32() const { return m_value
; }
123 operator volatile wxInt32
&() { return m_value
; }
125 wxAtomicInt32
& operator=(wxInt32 v
) { m_value
= v
; return *this; }
129 wxCriticalSectionLocker
lock(m_locker
);
135 wxCriticalSectionLocker
lock(m_locker
);
140 volatile wxInt32 m_value
;
141 wxCriticalSection m_locker
;
144 inline void wxAtomicInc(wxAtomicInt32
&value
) { value
.Inc(); }
145 inline wxInt32
wxAtomicDec(wxAtomicInt32
&value
) { return value
.Dec(); }
147 #else // !wxHAS_GENERIC_ATOMIC_OPS
149 inline void wxAtomicInc(wxInt32
&value
) { wxAtomicInc((wxUint32
&)value
); }
150 inline wxInt32
wxAtomicDec(wxInt32
&value
) { return wxAtomicDec((wxUint32
&)value
); }
152 typedef wxInt32 wxAtomicInt32
;
154 #endif // wxHAS_GENERIC_ATOMIC_OPS
156 // all the native implementations use 32 bits currently
157 // for a 64 bits implementation we could use (a future) wxAtomicInt64 as
159 typedef wxAtomicInt32 wxAtomicInt
;
161 #endif // _WX_ATOMIC_H_