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__)||(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
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;
118 // Typesafe wrapper around SGSwappable
119 template <typename T>
120 class Swappable : private SGAtomic
123 Swappable(const T& value) : SGAtomic(static_cast<unsigned>(value))
126 T operator() () const
128 return static_cast<T>(SGAtomic::operator unsigned ());
130 Swappable& operator=(const Swappable& rhs)
132 for (unsigned oldval = unsigned(*this);
133 !compareAndExchange(oldval, unsigned(rhs));
134 oldval = unsigned(*this))
138 bool compareAndSwap(const T& oldVal, const T& newVal)
140 return SGAtomic::compareAndExchange(static_cast<unsigned>(oldVal),
141 static_cast<unsigned>(newVal));