]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGAtomic.cxx
68fcf7757b2c81ddc621f0bd86758fbc7499905a
[simgear.git] / simgear / structure / SGAtomic.cxx
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 #ifdef HAVE_CONFIG_H
22 #  include <simgear_config.h>
23 #endif
24
25 #include "SGAtomic.hxx"
26
27 #if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
28
29 #if defined(_WIN32)
30 # include <windows.h>
31 #elif defined(GCC_ATOMIC_BUILTINS_FOUND)
32 #elif defined(__GNUC__) && defined(__i386__)
33 #else
34 # include <simgear/threads/SGGuard.hxx>
35 #endif
36
37 unsigned
38 SGAtomic::operator++()
39 {
40 #if defined(_WIN32)
41     return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
42 #elif defined(GCC_ATOMIC_BUILTINS_FOUND)
43     return __sync_add_and_fetch(&mValue, 1);
44 #elif defined(__GNUC__) && defined(__i386__)
45     register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
46     register unsigned result;
47     __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
48                          : "=r" (result), "=m" (*mem)
49                          : "0" (1), "m" (*mem)
50                          : "memory");
51     return result + 1;
52 #else
53     SGGuard<SGMutex> lock(mMutex);
54     return ++mValue;
55 #endif
56 }
57
58 unsigned
59 SGAtomic::operator--()
60 {
61 #if defined(_WIN32)
62     return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
63 #elif defined(GCC_ATOMIC_BUILTINS_FOUND)
64     return __sync_sub_and_fetch(&mValue, 1);
65 #elif defined(__GNUC__) && defined(__i386__)
66     register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
67     register unsigned result;
68     __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
69                          : "=r" (result), "=m" (*mem)
70                          : "0" (-1), "m" (*mem)
71                          : "memory");
72     return result - 1;
73 #else
74     SGGuard<SGMutex> lock(mMutex);
75     return --mValue;
76 #endif
77 }
78
79 SGAtomic::operator unsigned() const
80 {
81 #if defined(_WIN32)
82     return static_cast<unsigned const volatile &>(mValue);
83 #elif defined(GCC_ATOMIC_BUILTINS_FOUND)
84     __sync_synchronize();
85     return mValue;
86 #elif defined(__GNUC__) && defined(__i386__)
87     __asm__ __volatile__("": : : "memory");
88     return mValue;
89 #else
90     SGGuard<SGMutex> lock(mMutex);
91     return mValue;
92 #endif
93 }
94
95 bool
96 SGAtomic::compareAndExchange(unsigned oldValue, unsigned newValue)
97 {
98 #if defined(_WIN32)
99     long volatile* lvPtr = reinterpret_cast<long volatile*>(&mValue);
100     return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
101 #elif defined(GCC_ATOMIC_BUILTINS_FOUND)
102     return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
103 #elif defined(__GNUC__) && defined(__i386__)
104     register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
105     unsigned before;
106     __asm__ __volatile__("lock; cmpxchg{l} {%1,%2|%1,%2}"
107                          : "=a"(before)
108                          : "q"(newValue), "m"(*mem), "0"(oldValue)
109                          : "memory");
110     return before == oldValue;
111 #else
112     SGGuard<SGMutex> lock(mMutex);
113     if (mValue != oldValue)
114         return false;
115     mValue = newValue;
116     return true;
117 #endif
118 }
119
120 #endif