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

Revision 10927, 8.1 kB (checked in by robert, 4 years ago)

From Chuck Seberino, (submitted by Stephan Huber) Chuck's original message : "I have a patch to submit that fixes the following error when building against OSX 10.6.2."

RevLine 
[8440]1/* -*-c++-*- OpenThreads library, Copyright (C) 2008  The Open Thread Group
2 *
[10789]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
[8440]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.
[10789]7 *
[8440]8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[10789]10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[8440]11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef _OPENTHREADS_ATOMIC_
15#define _OPENTHREADS_ATOMIC_
16
17#include <OpenThreads/Config>
[8493]18#include <OpenThreads/Exports>
[8440]19
[10927]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
[8493]25#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
[10927]26# define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
[8440]27#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
28# include <atomic.h>
[9466]29# include "Mutex"
30# include "ScopedLock"
[8440]31#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
32# include "Mutex"
33# include "ScopedLock"
34#endif
35
[8493]36#if defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
37#define _OPENTHREADS_ATOMIC_INLINE
38#else
39#define _OPENTHREADS_ATOMIC_INLINE inline
40#endif
41
[8440]42namespace OpenThreads {
43
44/**
45 *  @class Atomic
46 *  @brief  This class provides an atomic increment and decrement operation.
47 */
[8493]48class OPENTHREAD_EXPORT_DIRECTIVE Atomic {
[8440]49 public:
50    Atomic(unsigned value = 0) : _value(value)
51    { }
[8493]52    _OPENTHREADS_ATOMIC_INLINE unsigned operator++();
53    _OPENTHREADS_ATOMIC_INLINE unsigned operator--();
[9059]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);
[8493]58    _OPENTHREADS_ATOMIC_INLINE operator unsigned() const;
[8440]59 private:
[8458]60
[8440]61    Atomic(const Atomic&);
62    Atomic& operator=(const Atomic&);
[10789]63
[8440]64#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
65    mutable Mutex _mutex;
66#endif
67#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
[8490]68    volatile long _value;
[9059]69#elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
70    volatile int32_t _value;
[8440]71#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
72    volatile uint_t _value;
[9466]73    mutable Mutex _mutex;  // needed for xor
[8440]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 */
[8493]83class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr {
[8440]84public:
[8493]85    AtomicPtr(void* ptr = 0) : _ptr(ptr)
[8440]86    { }
87    ~AtomicPtr()
88    { _ptr = 0; }
89
90    // assigns a new pointer
[8493]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{
[8440]109#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
[8493]110    return __sync_add_and_fetch(&_value, 1);
[8440]111#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
[8493]112    return __add_and_fetch(&_value, 1);
[8440]113#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
[8493]114    return atomic_inc_uint_nv(&_value);
[8440]115#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
[8493]116    ScopedLock<Mutex> lock(_mutex);
117    return ++_value;
[8440]118#else
[8493]119    return ++_value;
[8440]120#endif
[8493]121}
[8440]122
[8493]123_OPENTHREADS_ATOMIC_INLINE unsigned
124Atomic::operator--()
125{
[8440]126#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
[8493]127    return __sync_sub_and_fetch(&_value, 1);
[8440]128#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
[8493]129    return __sub_and_fetch(&_value, 1);
[8440]130#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
[8493]131    return atomic_dec_uint_nv(&_value);
[8440]132#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
[8493]133    ScopedLock<Mutex> lock(_mutex);
134    return --_value;
[8440]135#else
[8493]136    return --_value;
[8440]137#endif
[8493]138}
[8440]139
[9059]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);
[10789]170    _value |= value;
[9059]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)
[9466]186    ScopedLock<Mutex> lock(_mutex);
187    _value ^= value;
188    return _value;
[9059]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
[8493]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}
[8440]239
[8493]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)
[9467]248    return ptrOld == atomic_cas_ptr(&_ptr, const_cast<void*>(ptrOld), ptrNew);
[8493]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;
[8440]260#endif
[8493]261}
[8440]262
[8493]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
[8440]281}
282
[8493]283#endif // !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
284
285}
286
[8440]287#endif // _OPENTHREADS_ATOMIC_
Note: See TracBrowser for help on using the browser.