root/OpenSceneGraph/trunk/include/OpenThreads/Atomic @ 9467

Revision 9467, 8.1 kB (checked in by robert, 6 years ago)

From Andy Skinner, "I added a const_cast for a call to atomic_cas_ptr, which takes a void* and has been given a const void* const."

Line 
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_GCC_BUILTINS) && defined(__i386__)
21#define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
22#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
23#define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
24#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
25# include <atomic.h>
26# include "Mutex"
27# include "ScopedLock"
28#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
29# include <libkern/OSAtomic.h>
30# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
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, 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_
Note: See TracBrowser for help on using the browser.