3 * Copyright (C) 2005-2009 Mathias Froehlich
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #if defined(__GNUC__) && (4 <= __GNUC__) && (1 <= __GNUC_MINOR__) \
25 && (defined(__i386__) || defined(__x86_64__))
26 // No need to include something. Is a Compiler API ...
27 # define SGATOMIC_USE_GCC4_BUILTINS
28 #elif defined(__sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION>=730)
29 // No need to include something. Is a Compiler API ...
30 # define SGATOMIC_USE_MIPSPRO_BUILTINS
31 #elif defined(WIN32) && !defined ( __CYGWIN__ )
33 # define SGATOMIC_USE_WIN32_INTERLOCKED
35 // The sledge hammer ...
36 # include <simgear/threads/SGThread.hxx>
37 # include <simgear/threads/SGGuard.hxx>
42 SGAtomic(unsigned value = 0) : mValue(value)
46 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
47 return __sync_add_and_fetch(&mValue, 1);
48 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
49 return __add_and_fetch(&mValue, 1);
50 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
51 return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
53 SGGuard<SGMutex> lock(mMutex);
59 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
60 return __sync_sub_and_fetch(&mValue, 1);
61 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
62 return __sub_and_fetch(&mValue, 1);
63 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
64 return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
66 SGGuard<SGMutex> lock(mMutex);
70 operator unsigned() const
72 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
75 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
78 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
79 return static_cast<unsigned const volatile &>(mValue);
81 SGGuard<SGMutex> lock(mMutex);
86 bool compareAndExchange(unsigned oldValue, unsigned newValue)
88 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
89 return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
90 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
91 return __compare_and_swap(&mValue, oldValue, newValue);
92 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
93 long volatile* lvPtr = reinterpret_cast<long volatile*>(&mValue);
94 return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
96 SGGuard<SGMutex> lock(mMutex);
97 if (mValue != oldValue)
105 SGAtomic(const SGAtomic&);
106 SGAtomic& operator=(const SGAtomic&);
108 #if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
109 && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \
110 && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
111 mutable SGMutex mMutex;
116 // Value that can be atomically compared and swapped.
120 typedef unsigned long value_type;
121 SGSwappable(unsigned long value = 0) : mValue(value) {}
122 operator unsigned long() const
124 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
125 __sync_synchronize();
127 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
130 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
131 return static_cast<long const volatile &>(mValue);
133 SGGuard<SGMutex> lock(mMutex);
138 bool compareAndSwap(unsigned long oldVal, unsigned long newVal)
140 #if defined(SGATOMIC_USE_GCC4_BUILTINS)
141 return __sync_bool_compare_and_swap(&mValue, oldVal, newVal);
142 #elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
143 return __compare_and_swap(&mValue, oldVal, newVal);
144 #elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
146 = InterlockedCompareExchange(reinterpret_cast<long volatile*>(&mValue),
149 return previous == (long)oldVal;
151 SGGuard<SGMutex> lock(mMutex);
152 if (oldVal == mValue) {
162 SGSwappable(const SGAtomic&);
163 SGSwappable& operator=(const SGAtomic&);
165 #if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
166 && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \
167 && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
168 mutable SGMutex mMutex;
170 #ifdef SGATOMIC_USE_WIN32_INTERLOCKED
171 __declspec(align(32))
179 // Typesafe wrapper around SGSwappable
180 template <typename T>
181 class Swappable : private SGSwappable
184 Swappable(const T& value) : SGSwappable(static_cast<value_type>(value))
187 T operator() () const
189 return static_cast<T>(SGSwappable::operator unsigned long ());
191 bool compareAndSwap(const T& oldVal, const T& newVal)
193 return SGSwappable::compareAndSwap(static_cast<value_type>(oldVal),
194 static_cast<value_type>(newVal));