]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGAtomic.hxx
Rework SGAtomic, move more into the implementation.
[simgear.git] / simgear / structure / SGAtomic.hxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2005-2009,2011 Mathias Froehlich 
4  *
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.
9  *
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.
14  *
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.
18  *
19  */
20
21 #ifndef SGAtomic_HXX
22 #define SGAtomic_HXX
23
24 #if defined(__GNUC__) && ((4 < __GNUC__)||(4 == __GNUC__ && 1 <= __GNUC_MINOR__)) && \
25     defined(__x86_64__)
26 // No need to include something. Is a Compiler API ...
27 # define SGATOMIC_USE_GCC4_BUILTINS
28 #elif defined(__GNUC__) && defined(__i386__)
29 # define SGATOMIC_USE_LIBRARY_FUNCTIONS
30 #elif defined(__sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION>=730)
31 // No need to include something. Is a Compiler API ...
32 # define SGATOMIC_USE_MIPSPRO_BUILTINS
33 #elif defined(_WIN32)
34 # define SGATOMIC_USE_LIBRARY_FUNCTIONS
35 #else
36 // The sledge hammer ...
37 # define SGATOMIC_USE_LIBRARY_FUNCTIONS
38 # include <simgear/threads/SGThread.hxx>
39 #endif
40
41 class SGAtomic {
42 public:
43   SGAtomic(unsigned value = 0) : mValue(value)
44   { }
45
46 #if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
47   unsigned operator++();
48 #else
49   unsigned operator++()
50   {
51 # if defined(SGATOMIC_USE_GCC4_BUILTINS)
52     return __sync_add_and_fetch(&mValue, 1);
53 # elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
54     return __add_and_fetch(&mValue, 1);
55 # else
56 #  error
57 # endif
58   }
59 #endif
60
61 #if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
62   unsigned operator--();
63 #else
64   unsigned operator--()
65   {
66 # if defined(SGATOMIC_USE_GCC4_BUILTINS)
67     return __sync_sub_and_fetch(&mValue, 1);
68 # elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
69     return __sub_and_fetch(&mValue, 1);
70 # else
71 #  error
72 # endif
73   }
74 #endif
75
76 #if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
77   operator unsigned() const;
78 #else
79   operator unsigned() const
80   {
81 # if defined(SGATOMIC_USE_GCC4_BUILTINS)
82     __sync_synchronize();
83     return mValue;
84 # elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
85     __synchronize();
86     return mValue;
87 # else
88 #  error
89 # endif
90   }
91 #endif
92
93 #if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
94   bool compareAndExchange(unsigned oldValue, unsigned newValue);
95 #else
96   bool compareAndExchange(unsigned oldValue, unsigned newValue)
97   {
98 # if defined(SGATOMIC_USE_GCC4_BUILTINS)
99     return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
100 # elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
101     return __compare_and_swap(&mValue, oldValue, newValue);
102 # else
103 #  error
104 # endif
105   }
106 #endif
107
108 private:
109   SGAtomic(const SGAtomic&);
110   SGAtomic& operator=(const SGAtomic&);
111
112 #if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
113   && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \
114   && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
115   mutable SGMutex mMutex;
116 #endif
117   unsigned mValue;
118 };
119
120 namespace simgear
121 {
122 // Typesafe wrapper around SGSwappable
123 template <typename T>
124 class Swappable : private SGAtomic
125 {
126 public:
127     Swappable(const T& value) : SGAtomic(static_cast<unsigned>(value))
128     {
129     }
130     T operator() () const
131     {
132         return static_cast<T>(SGAtomic::operator unsigned ());
133     }
134     Swappable& operator=(const Swappable& rhs)
135     {
136         for (unsigned oldval = unsigned(*this);
137              !compareAndExchange(oldval, unsigned(rhs));
138              oldval = unsigned(*this))
139             ;
140         return *this;
141     }
142     bool compareAndSwap(const T& oldVal, const T& newVal)
143     {
144         return SGAtomic::compareAndExchange(static_cast<unsigned>(oldVal),
145                                            static_cast<unsigned>(newVal));
146     }
147 };
148 }
149 #endif