Ice 3.7 C++98 API Reference
Loading...
Searching...
No Matches
Atomic.h
Go to the documentation of this file.
1//
2// Copyright (c) ZeroC, Inc. All rights reserved.
3//
4
5#ifndef ICE_UTIL_ATOMIC_H
6#define ICE_UTIL_ATOMIC_H
7
8#if ((defined(ICE_CPP11_COMPILER) && defined(_MSC_VER) && (_MSC_VER > 1600)) || \
9 (defined(ICE_CPP11_COMPILER) && !defined(_MSC_VER)))
10# define ICE_CPP11_COMPILER_HAS_ATOMIC
11#endif
12
13#if defined(ICE_CPP11_COMPILER_HAS_ATOMIC)
14# include <atomic>
15#elif defined(ICE_USE_MUTEX_SHARED)
16
17# include <IceUtil/Mutex.h>
18
19// Using the gcc builtins requires gcc 4.1 or better. For Linux, i386
20// doesn't work. Apple is supported for all architectures. Sun only
21// supports sparc (32 and 64 bit).
22
23#elif ((defined(__GNUC__) && (((__GNUC__* 100) + __GNUC_MINOR__) >= 401)) || __clang__) && \
24 ((defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \
25 defined(__APPLE__) || \
26 (defined(__linux__) && \
27 (defined(__i486) || defined(__i586) || \
28 defined(__i686) || defined(__x86_64))))
29
30# define ICE_HAS_GCC_BUILTINS
31
32#elif defined(_WIN32)
33// Nothing to include
34#else
35// Use a simple mutex
36# include <IceUtil/Mutex.h>
37#endif
38
39namespace IceUtilInternal
40{
41
42#ifdef ICE_CPP11_COMPILER_HAS_ATOMIC
43typedef std::atomic<int> Atomic;
44#else
45
46#if defined(_WIN32)
47//
48// volatile here is required by InterlockedExchangeXXX
49// family functions.
50//
51# if defined(__MINGW32__) || (defined(_MSC_VER) && (_MSC_VER <= 1500))
52typedef volatile LONG ATOMIC_T;
53# else
54typedef unsigned int ATOMIC_T;
55# endif
56#else
57typedef int ATOMIC_T;
58#endif
59
60//
61// This is temporary and very partial placeholder for std::atomic,
62// which is not yet widely available.
63//
64class ICE_API Atomic : public IceUtil::noncopyable
65{
66public:
67
68 Atomic() :
69 _ref(0)
70 {
71 }
72
73 Atomic(int desired) :
74 _ref(desired)
75 {
76 }
77
78 inline int fetch_add(int value)
79 {
80#if defined(_WIN32)
81 return InterlockedExchangeAdd(&_ref, value);
82#elif defined(ICE_HAS_GCC_BUILTINS)
83 return __sync_fetch_and_add(&_ref, value);
84#else
85 IceUtil::Mutex::Lock sync(_mutex);
86 int tmp = _ref;
87 _ref += value;
88 return tmp;
89#endif
90 }
91
92 inline int fetch_sub(int value)
93 {
94#if defined(_WIN32)
95# if defined(__MINGW32__) || (defined(_MSC_VER) && (_MSC_VER <= 1500))
96 return InterlockedExchangeAdd(&_ref, -value);
97# else
98 return InterlockedExchangeSubtract(&_ref, value);
99#endif
100#elif defined(ICE_HAS_GCC_BUILTINS)
101 return __sync_fetch_and_sub(&_ref, value);
102#else
103 IceUtil::Mutex::Lock sync(_mutex);
104 ATOMIC_T tmp = _ref;
105 _ref -= value;
106 return tmp;
107#endif
108 }
109
110 inline int load() const
111 {
112#if defined(_WIN32)
113 return InterlockedExchangeAdd(const_cast<ATOMIC_T*>(&_ref), 0);
114#elif defined(ICE_HAS_GCC_BUILTINS)
115 return __sync_fetch_and_add(const_cast<ATOMIC_T*>(&_ref), 0);
116#else
117 IceUtil::Mutex::Lock sync(_mutex);
118 return _ref;
119#endif
120 }
121
122 inline int exchange(int value)
123 {
124#if defined(_WIN32)
125 return InterlockedExchange(&_ref, value);
126#elif defined(ICE_HAS_GCC_BUILTINS)
127 __sync_synchronize();
128 return __sync_lock_test_and_set(&_ref, value);
129#else
130 IceUtil::Mutex::Lock sync(_mutex);
131 int tmp = _ref;
132 _ref = value;
133 return tmp;
134#endif
135 }
136
137 inline int operator++()
138 {
139 return fetch_add(1) + 1;
140 }
141
142 inline int operator--()
143 {
144 return fetch_sub(1) - 1;
145 }
146
147 inline int operator++(int)
148 {
149 return fetch_add(1);
150 }
151
152 inline int operator--(int)
153 {
154 return fetch_sub(1);
155 }
156
157 inline operator int()
158 {
159 return load();
160 }
161
162 inline operator int() const
163 {
164 return load();
165 }
166
167private:
168
169 ATOMIC_T _ref;
170#if !defined(_WIN32) && !defined(ICE_HAS_GCC_BUILTINS)
171 IceUtil::Mutex _mutex;
172#endif
173};
174
175#endif
176
177}
178
179#endif
#define ICE_API
Definition Config.h:197
LockT< Mutex > Lock
Definition Mutex.h:39