comparison include/SDL_atomic.h @ 5099:b938ad843e52

More fixes for compilation on Visual Studio
author Sam Lantinga <slouken@libsdl.org>
date Tue, 25 Jan 2011 18:02:41 -0800
parents e4301cde4de1
children 470ede30189c
comparison
equal deleted inserted replaced
5098:e4301cde4de1 5099:b938ad843e52
125 */ 125 */
126 #ifdef _MSC_VER 126 #ifdef _MSC_VER
127 void _ReadWriteBarrier(void); 127 void _ReadWriteBarrier(void);
128 #pragma intrinsic(_ReadWriteBarrier) 128 #pragma intrinsic(_ReadWriteBarrier)
129 #define SDL_CompilerBarrier() _ReadWriteBarrier() 129 #define SDL_CompilerBarrier() _ReadWriteBarrier()
130 #elif __GNUC__ 130 #elif defined(__GNUC__)
131 #define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory") 131 #define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
132 #else 132 #else
133 #define SDL_CompilerBarrier() \ 133 #define SDL_CompilerBarrier() \
134 ({ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }) 134 ({ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); })
135 #endif 135 #endif
137 /* Platform specific optimized versions of the atomic functions, 137 /* Platform specific optimized versions of the atomic functions,
138 * you can disable these by defining SDL_DISABLE_ATOMIC_INLINE 138 * you can disable these by defining SDL_DISABLE_ATOMIC_INLINE
139 */ 139 */
140 #ifndef SDL_DISABLE_ATOMIC_INLINE 140 #ifndef SDL_DISABLE_ATOMIC_INLINE
141 141
142 #if HAVE_MSC_ATOMICS 142 #ifdef HAVE_MSC_ATOMICS
143 143
144 #define SDL_AtomicSet(a, v) _InterlockedExchange((long*)&(a)->value, (v)) 144 #define SDL_AtomicSet(a, v) _InterlockedExchange((long*)&(a)->value, (v))
145 #define SDL_AtomicAdd(a, v) _InterlockedExchangeAdd((long*)&(a)->value, (v)) 145 #define SDL_AtomicAdd(a, v) _InterlockedExchangeAdd((long*)&(a)->value, (v))
146 #define SDL_AtomicCAS(a, oldval, newval) (_InterlockedCompareExchange((long*)&(a)->value, (newval), (oldval)) == (oldval)) 146 #define SDL_AtomicCAS(a, oldval, newval) (_InterlockedCompareExchange((long*)&(a)->value, (newval), (oldval)) == (oldval))
147 #define SDL_AtomicSetPtr(a, v) _InterlockedExchangePointer((a), (v)) 147 #define SDL_AtomicSetPtr(a, v) _InterlockedExchangePointer((a), (v))
149 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchange((long*)(a), (long)(newval), (long)(oldval)) == (long)(oldval)) 149 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchange((long*)(a), (long)(newval), (long)(oldval)) == (long)(oldval))
150 #else 150 #else
151 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchangePointer((a), (newval), (oldval)) == (oldval)) 151 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchangePointer((a), (newval), (oldval)) == (oldval))
152 #endif 152 #endif
153 153
154 #elif __MACOSX__ 154 #elif defined(__MACOSX__)
155 #include <libkern/OSAtomic.h> 155 #include <libkern/OSAtomic.h>
156 156
157 #define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((oldval), (newval), &(a)->value) 157 #define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((oldval), (newval), &(a)->value)
158 #if SIZEOF_VOIDP == 4 158 #if SIZEOF_VOIDP == 4
159 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a)) 159 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a))
160 #elif SIZEOF_VOIDP == 8 160 #elif SIZEOF_VOIDP == 8
161 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a)) 161 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a))
162 #endif 162 #endif
163 163
164 #elif HAVE_GCC_ATOMICS 164 #elif defined(HAVE_GCC_ATOMICS)
165 165
166 #define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v) 166 #define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v)
167 #define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v) 167 #define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v)
168 #define SDL_AtomicSetPtr(a, v) __sync_lock_test_and_set(a, v) 168 #define SDL_AtomicSetPtr(a, v) __sync_lock_test_and_set(a, v)
169 #define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval) 169 #define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval)
181 #ifndef SDL_atomic_t_defined 181 #ifndef SDL_atomic_t_defined
182 typedef struct { int value; } SDL_atomic_t; 182 typedef struct { int value; } SDL_atomic_t;
183 #endif 183 #endif
184 184
185 /** 185 /**
186 * \brief Set an atomic variable to a value.
187 *
188 * \return The previous value of the atomic variable.
189 */
190 #ifndef SDL_AtomicSet
191 #define SDL_AtomicSet(a, v) \
192 ({ \
193 int _value; \
194 do { \
195 _value = (a)->value; \
196 } while (!SDL_AtomicCAS(a, _value, (v))); \
197 _value; \
198 })
199 #endif
200
201 /**
202 * \brief Get the value of an atomic variable
203 */
204 #ifndef SDL_AtomicGet
205 #define SDL_AtomicGet(a) \
206 ({ \
207 int _value = (a)->value; \
208 SDL_CompilerBarrier(); \
209 _value; \
210 })
211 #endif
212
213 /**
214 * \brief Add to an atomic variable.
215 *
216 * \return The previous value of the atomic variable.
217 *
218 * \note This same style can be used for any number operation
219 */
220 #ifndef SDL_AtomicAdd
221 #define SDL_AtomicAdd(a, v) \
222 ({ \
223 int _value; \
224 do { \
225 _value = (a)->value; \
226 } while (!SDL_AtomicCAS(a, _value, (_value + (v)))); \
227 _value; \
228 })
229 #endif
230
231 /**
232 * \brief Increment an atomic variable used as a reference count.
233 */
234 #ifndef SDL_AtomicIncRef
235 #define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
236 #endif
237
238 /**
239 * \brief Decrement an atomic variable used as a reference count.
240 *
241 * \return SDL_TRUE if the variable reached zero after decrementing,
242 * SDL_FALSE otherwise
243 */
244 #ifndef SDL_AtomicDecRef
245 #define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
246 #endif
247
248 /**
249 * \brief Set an atomic variable to a new value if it is currently an old value. 186 * \brief Set an atomic variable to a new value if it is currently an old value.
250 * 187 *
251 * \return SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise. 188 * \return SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
252 * 189 *
253 * \note If you don't know what this function is for, you shouldn't use it! 190 * \note If you don't know what this function is for, you shouldn't use it!
256 #define SDL_AtomicCAS SDL_AtomicCAS_ 193 #define SDL_AtomicCAS SDL_AtomicCAS_
257 #endif 194 #endif
258 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS_(SDL_atomic_t *a, int oldval, int newval); 195 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS_(SDL_atomic_t *a, int oldval, int newval);
259 196
260 /** 197 /**
261 * \brief Set a pointer to a value atomically. 198 * \brief Set an atomic variable to a value.
262 * 199 *
263 * \return The previous value of the pointer. 200 * \return The previous value of the atomic variable.
264 */ 201 */
265 #ifndef SDL_AtomicSetPtr 202 #ifndef SDL_AtomicSet
266 #define SDL_AtomicSetPtr(a, v) \ 203 static __inline__ int SDL_AtomicSet(SDL_atomic_t *a, int v)
267 ({ \ 204 {
268 void* _value; \ 205 int value;
269 do { \ 206 do {
270 _value = *(a); \ 207 value = a->value;
271 } while (!SDL_AtomicCASPtr(a, _value, (v))); \ 208 } while (!SDL_AtomicCAS(a, value, v));
272 _value; \ 209 return value;
273 }) 210 }
274 #endif 211 #endif
275 212
276 /** 213 /**
277 * \brief Get the value of a pointer atomically. 214 * \brief Get the value of an atomic variable
278 */ 215 */
279 #ifndef SDL_AtomicGetPtr 216 #ifndef SDL_AtomicGet
280 #define SDL_AtomicGetPtr(a) \ 217 static __inline__ int SDL_AtomicGet(SDL_atomic_t *a)
281 ({ \ 218 {
282 void* _value = *(a); \ 219 int value = a->value;
283 SDL_CompilerBarrier(); \ 220 SDL_CompilerBarrier();
284 _value; \ 221 return value;
285 }) 222 }
223 #endif
224
225 /**
226 * \brief Add to an atomic variable.
227 *
228 * \return The previous value of the atomic variable.
229 *
230 * \note This same style can be used for any number operation
231 */
232 #ifndef SDL_AtomicAdd
233 static __inline__ int SDL_AtomicAdd(SDL_atomic_t *a, int v)
234 {
235 int value;
236 do {
237 value = a->value;
238 } while (!SDL_AtomicCAS(a, value, (value + v)));
239 return value;
240 }
241 #endif
242
243 /**
244 * \brief Increment an atomic variable used as a reference count.
245 */
246 #ifndef SDL_AtomicIncRef
247 #define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
248 #endif
249
250 /**
251 * \brief Decrement an atomic variable used as a reference count.
252 *
253 * \return SDL_TRUE if the variable reached zero after decrementing,
254 * SDL_FALSE otherwise
255 */
256 #ifndef SDL_AtomicDecRef
257 #define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
286 #endif 258 #endif
287 259
288 /** 260 /**
289 * \brief Set a pointer to a new value if it is currently an old value. 261 * \brief Set a pointer to a new value if it is currently an old value.
290 * 262 *
295 #ifndef SDL_AtomicCASPtr 267 #ifndef SDL_AtomicCASPtr
296 #define SDL_AtomicCASPtr SDL_AtomicCASPtr_ 268 #define SDL_AtomicCASPtr SDL_AtomicCASPtr_
297 #endif 269 #endif
298 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr_(void **a, void *oldval, void *newval); 270 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr_(void **a, void *oldval, void *newval);
299 271
272 /**
273 * \brief Set a pointer to a value atomically.
274 *
275 * \return The previous value of the pointer.
276 */
277 #ifndef SDL_AtomicSetPtr
278 static __inline__ void* SDL_AtomicSetPtr(void* *a, void* v)
279 {
280 void* value;
281 do {
282 value = *a;
283 } while (!SDL_AtomicCASPtr(a, value, v));
284 return value;
285 }
286 #endif
287
288 /**
289 * \brief Get the value of a pointer atomically.
290 */
291 #ifndef SDL_AtomicGetPtr
292 static __inline__ void* SDL_AtomicGetPtr(void* *a)
293 {
294 void* value = *a;
295 SDL_CompilerBarrier();
296 return value;
297 }
298 #endif
299
300
300 /* Ends C function definitions when using C++ */ 301 /* Ends C function definitions when using C++ */
301 #ifdef __cplusplus 302 #ifdef __cplusplus
302 /* *INDENT-OFF* */ 303 /* *INDENT-OFF* */
303 } 304 }
304 /* *INDENT-ON* */ 305 /* *INDENT-ON* */