]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: wx/atomic.h | |
3 | // Purpose: functions to manipulate atomically integers and pointers | |
4 | // Author: Armel Asselin | |
5 | // Created: 12/13/2006 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) Armel Asselin | |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_ATOMIC_H_ | |
12 | #define _WX_ATOMIC_H_ | |
13 | ||
14 | // ---------------------------------------------------------------------------- | |
15 | // headers | |
16 | // ---------------------------------------------------------------------------- | |
17 | ||
18 | // get the value of wxUSE_THREADS configuration flag | |
19 | #include "wx/defs.h" | |
20 | ||
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). | |
25 | ||
26 | #if wxUSE_THREADS | |
27 | ||
28 | #if defined(__WXMSW__) | |
29 | ||
30 | // include standard Windows headers | |
31 | #include "wx/msw/wrapwin.h" | |
32 | ||
33 | inline void wxAtomicInc (wxUint32 &value) | |
34 | { | |
35 | InterlockedIncrement ((LONG*)&value); | |
36 | } | |
37 | ||
38 | inline wxUint32 wxAtomicDec (wxUint32 &value) | |
39 | { | |
40 | return InterlockedDecrement ((LONG*)&value); | |
41 | } | |
42 | ||
43 | #elif defined(__WXMAC__) || defined(__DARWIN__) | |
44 | ||
45 | #include "libkern/OSAtomic.h" | |
46 | inline void wxAtomicInc (wxUint32 &value) | |
47 | { | |
48 | OSAtomicIncrement32 ((int32_t*)&value); | |
49 | } | |
50 | ||
51 | inline wxUint32 wxAtomicDec (wxUint32 &value) | |
52 | { | |
53 | return OSAtomicDecrement32 ((int32_t*)&value); | |
54 | } | |
55 | ||
56 | #elif defined(__LINUX__) | |
57 | ||
58 | #include <asm/atomic.h> | |
59 | ||
60 | inline void wxAtomicInc (wxUint32 &value) | |
61 | { | |
62 | atomic_inc ((atomic_t*)&value); | |
63 | } | |
64 | ||
65 | inline wxUint32 wxAtomicDec (wxUint32 &value) | |
66 | { | |
67 | return atomic_dec_and_test ((atomic_t*)&value) ? 0 : 1; | |
68 | } | |
69 | ||
70 | #elif defined (__SOLARIS__) | |
71 | ||
72 | #include <atomic.h> | |
73 | ||
74 | inline void wxAtomicInc (wxUint32 &value) | |
75 | { | |
76 | atomic_add_32 ((uint32_t*)&value, 1); | |
77 | } | |
78 | ||
79 | inline wxUint32 wxAtomicDec (wxUint32 &value) | |
80 | { | |
81 | return atomic_add_32_nv ((uint32_t*)&value, (uint32_t)-1); | |
82 | } | |
83 | ||
84 | #else // unknown platform | |
85 | ||
86 | // it will result in inclusion if the generic implementation code a bit later in this page | |
87 | #define wxHAS_GENERIC_ATOMIC_OPS 1 | |
88 | ||
89 | #endif // unknown platform | |
90 | ||
91 | #else // else of wxUSE_THREADS | |
92 | // if no threads are used we can safely use simple ++/-- | |
93 | ||
94 | inline void wxAtomicInc (wxUint32 &value) { ++value; } | |
95 | inline wxUint32 wxAtomicDec (wxUint32 &value) { return --value; } | |
96 | ||
97 | #endif // !wxUSE_THREADS | |
98 | ||
99 | // ---------------------------------------------------------------------------- | |
100 | // proxies to actual implementations, but for various other types with same | |
101 | // behaviour | |
102 | // ---------------------------------------------------------------------------- | |
103 | ||
104 | #if !defined(wxHAS_GENERIC_ATOMIC_OPS) | |
105 | #define wxHAS_GENERIC_ATOMIC_OPS 0 | |
106 | #endif | |
107 | ||
108 | #if wxHAS_GENERIC_ATOMIC_OPS | |
109 | #include "wx/thread.h" // for wxCriticalSection | |
110 | ||
111 | class wxAtomicInt32 | |
112 | { | |
113 | public: | |
114 | wxAtomicInt() { } // non initialized for consistency with basic int type | |
115 | wxAtomicInt(wxInt32 v) : m_value(v) { } | |
116 | ||
117 | operator wxInt32() const { return m_value; } | |
118 | operator wxInt32&() { return m_value; } | |
119 | ||
120 | wxAtomicInt& operator=(wxInt32 v) { m_value = v; return *this; } | |
121 | ||
122 | void Inc() | |
123 | { | |
124 | wxCriticalSectionLocker lock(m_locker); | |
125 | ++m_value; | |
126 | } | |
127 | ||
128 | wxInt32 Dec() | |
129 | { | |
130 | wxCriticalSectionLocker lock(m_locker); | |
131 | return --m_value; | |
132 | } | |
133 | ||
134 | private: | |
135 | volatile wxInt32 m_value; | |
136 | wxCriticalSection m_locker; | |
137 | }; | |
138 | ||
139 | inline void wxAtomicInc(wxAtomicInt &value) { value.Inc(); } | |
140 | inline wxInt32 wxAtomicDec(wxAtomicInt &value) { return value.Dec(); } | |
141 | ||
142 | #else // !wxHAS_GENERIC_ATOMIC_OPS | |
143 | ||
144 | inline void wxAtomicInc(wxInt32 &value) { wxAtomicInc((wxUint32&)value); } | |
145 | inline wxInt32 wxAtomicDec(wxInt32 &value) { return wxAtomicDec((wxUint32&)value); } | |
146 | ||
147 | typedef wxInt32 wxAtomicInt32; | |
148 | ||
149 | #endif // wxHAS_GENERIC_ATOMIC_OPS | |
150 | ||
151 | // all the native implementations use 32 bits currently | |
152 | // for a 64 bits implementation we could use (a future) wxAtomicInt64 as | |
153 | // default type | |
154 | typedef wxAtomicInt32 wxAtomicInt; | |
155 | ||
156 | #endif // _WX_ATOMIC_H_ |