OpenThreads
Atomic
Go to the documentation of this file.
1/* -*-c++-*- OpenThreads library, Copyright (C) 2008 The Open Thread Group
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef _OPENTHREADS_ATOMIC_
15#define _OPENTHREADS_ATOMIC_
16
17#include <OpenThreads/Config>
18#include <OpenThreads/Exports>
19
20#if defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
21# include <libkern/OSAtomic.h>
22# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
23#elif defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) && defined(__i386__)
24# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
25#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
26# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
27#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
28# include <atomic.h>
29# include "Mutex"
30# include "ScopedLock"
31#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
32# include "Mutex"
33# include "ScopedLock"
34#endif
35
36#if defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
37#define _OPENTHREADS_ATOMIC_INLINE
38#else
39#define _OPENTHREADS_ATOMIC_INLINE inline
40#endif
41
42namespace OpenThreads {
43
44/**
45 * @class Atomic
46 * @brief This class provides an atomic increment and decrement operation.
47 */
48class OPENTHREAD_EXPORT_DIRECTIVE Atomic {
49 public:
50 Atomic(unsigned value = 0) : _value(value)
51 { }
52 _OPENTHREADS_ATOMIC_INLINE unsigned operator++();
53 _OPENTHREADS_ATOMIC_INLINE unsigned operator--();
54 _OPENTHREADS_ATOMIC_INLINE unsigned AND(unsigned value);
55 _OPENTHREADS_ATOMIC_INLINE unsigned OR(unsigned value);
56 _OPENTHREADS_ATOMIC_INLINE unsigned XOR(unsigned value);
57 _OPENTHREADS_ATOMIC_INLINE unsigned exchange(unsigned value = 0);
58 _OPENTHREADS_ATOMIC_INLINE operator unsigned() const;
59 private:
60
61 Atomic(const Atomic&);
62 Atomic& operator=(const Atomic&);
63
64#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
65 mutable Mutex _mutex;
66#endif
67#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
68 volatile long _value;
69#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
70 volatile int32_t _value;
71#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
72 volatile uint_t _value;
73 mutable Mutex _mutex; // needed for xor
74#else
75 volatile unsigned _value;
76#endif
77};
78
79/**
80 * @class AtomicPtr
81 * @brief This class provides an atomic pointer assignment using cas operations.
82 */
83class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr {
84public:
85 AtomicPtr(void* ptr = 0) : _ptr(ptr)
86 { }
87 ~AtomicPtr()
88 { _ptr = 0; }
89
90 // assigns a new pointer
91 _OPENTHREADS_ATOMIC_INLINE bool assign(void* ptrNew, const void* const ptrOld);
92 _OPENTHREADS_ATOMIC_INLINE void* get() const;
93
94private:
95 AtomicPtr(const AtomicPtr&);
96 AtomicPtr& operator=(const AtomicPtr&);
97
98#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
99 mutable Mutex _mutex;
100#endif
101 void* volatile _ptr;
102};
103
104#if !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
105
106_OPENTHREADS_ATOMIC_INLINE unsigned
107Atomic::operator++()
108{
109#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
110 return __sync_add_and_fetch(&_value, 1);
111#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
112 return __add_and_fetch(&_value, 1);
113#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
114 return atomic_inc_uint_nv(&_value);
115#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
116 ScopedLock<Mutex> lock(_mutex);
117 return ++_value;
118#else
119 return ++_value;
120#endif
121}
122
123_OPENTHREADS_ATOMIC_INLINE unsigned
124Atomic::operator--()
125{
126#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
127 return __sync_sub_and_fetch(&_value, 1);
128#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
129 return __sub_and_fetch(&_value, 1);
130#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
131 return atomic_dec_uint_nv(&_value);
132#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
133 ScopedLock<Mutex> lock(_mutex);
134 return --_value;
135#else
136 return --_value;
137#endif
138}
139
140_OPENTHREADS_ATOMIC_INLINE unsigned
141Atomic::AND(unsigned value)
142{
143#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
144 return __sync_fetch_and_and(&_value, value);
145#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
146 return __and_and_fetch(&_value, value);
147#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
148 return atomic_and_uint_nv(&_value, value);
149#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
150 ScopedLock<Mutex> lock(_mutex);
151 _value &= value;
152 return _value;
153#else
154 _value &= value;
155 return _value;
156#endif
157}
158
159_OPENTHREADS_ATOMIC_INLINE unsigned
160Atomic::OR(unsigned value)
161{
162#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
163 return __sync_fetch_and_or(&_value, value);
164#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
165 return __or_and_fetch(&_value, value);
166#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
167 return atomic_or_uint_nv(&_value, value);
168#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
169 ScopedLock<Mutex> lock(_mutex);
170 _value |= value;
171 return _value;
172#else
173 _value |= value;
174 return _value;
175#endif
176}
177
178_OPENTHREADS_ATOMIC_INLINE unsigned
179Atomic::XOR(unsigned value)
180{
181#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
182 return __sync_fetch_and_xor(&_value, value);
183#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
184 return __xor_and_fetch(&_value, value);
185#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
186 ScopedLock<Mutex> lock(_mutex);
187 _value ^= value;
188 return _value;
189#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
190 ScopedLock<Mutex> lock(_mutex);
191 _value ^= value;
192 return _value;
193#else
194 _value ^= value;
195 return _value;
196#endif
197}
198
199_OPENTHREADS_ATOMIC_INLINE unsigned
200Atomic::exchange(unsigned value)
201{
202#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
203 return __sync_lock_test_and_set(&_value, value);
204#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
205 return __compare_and_swap(&_value, _value, value);
206#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
207 return atomic_cas_uint(&_value, _value, value);
208#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
209 ScopedLock<Mutex> lock(_mutex);
210 unsigned oldval = _value;
211 _value = value;
212 return oldval;
213#else
214 unsigned oldval = _value;
215 _value = value;
216 return oldval;
217#endif
218}
219
220_OPENTHREADS_ATOMIC_INLINE
221Atomic::operator unsigned() const
222{
223#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
224 __sync_synchronize();
225 return _value;
226#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
227 __synchronize();
228 return _value;
229#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
230 membar_consumer(); // Hmm, do we need???
231 return _value;
232#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
233 ScopedLock<Mutex> lock(_mutex);
234 return _value;
235#else
236 return _value;
237#endif
238}
239
240_OPENTHREADS_ATOMIC_INLINE bool
241AtomicPtr::assign(void* ptrNew, const void* const ptrOld)
242{
243#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
244 return __sync_bool_compare_and_swap(&_ptr, (void *)ptrOld, ptrNew);
245#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
246 return __compare_and_swap((unsigned long*)&_ptr, (unsigned long)ptrOld, (unsigned long)ptrNew);
247#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
248 return ptrOld == atomic_cas_ptr(&_ptr, const_cast<void*>(ptrOld), ptrNew);
249#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
250 ScopedLock<Mutex> lock(_mutex);
251 if (_ptr != ptrOld)
252 return false;
253 _ptr = ptrNew;
254 return true;
255#else
256 if (_ptr != ptrOld)
257 return false;
258 _ptr = ptrNew;
259 return true;
260#endif
261}
262
263_OPENTHREADS_ATOMIC_INLINE void*
264AtomicPtr::get() const
265{
266#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
267 __sync_synchronize();
268 return _ptr;
269#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
270 __synchronize();
271 return _ptr;
272#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
273 membar_consumer(); // Hmm, do we need???
274 return _ptr;
275#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
276 ScopedLock<Mutex> lock(_mutex);
277 return _ptr;
278#else
279 return _ptr;
280#endif
281}
282
283#endif // !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
284
285}
286
287#endif // _OPENTHREADS_ATOMIC_

osg logo
Generated at Mon Jan 22 2024 00:00:00 for the OpenThreads by doxygen 1.10.0.