comparison include/SDL_atomic.h @ 5004:0c72ae7b7cb2

Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics. Changed the CAS return value to bool, so it's efficient with OSAtomicCompareAndSwap32Barrier() Added an atomic test adapted from code by Michael Davidsaver
author Sam Lantinga <slouken@libsdl.org>
date Sun, 16 Jan 2011 15:16:39 -0800
parents 3a95a2b93eb3
children 7f0265279b68
comparison
equal deleted inserted replaced
5003:3a95a2b93eb3 5004:0c72ae7b7cb2
106 extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); 106 extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
107 107
108 /*@}*//*SDL AtomicLock*/ 108 /*@}*//*SDL AtomicLock*/
109 109
110 /* Platform specific optimized versions of the atomic functions */ 110 /* Platform specific optimized versions of the atomic functions */
111 /* None yet... */ 111 #if defined(__WIN32__)
112 #define WIN32_LEAN_AND_MEAN
113 #include <windows.h>
114
115 #define SDL_AtomicSet(a, v) InterlockedExchange(&(a)->value, v)
116 #define SDL_AtomicGet(a) ((a)->value)
117 #define SDL_AtomicAdd(a, v) InterlockedAdd(&(a)->value, v)
118 #define SDL_AtomicCAS(a, oldval, newval) (InterlockedCompareExchange(&(a)->value, newval, oldval) == (oldval))
119 #define SDL_AtomicSetPtr(a, v) InterlockedExchangePointer(a, v)
120 #define SDL_AtomicGetPtr(a) (*(a))
121 #define SDL_AtomicCASPtr(a, oldval, newval) (InterlockedCompareExchangePointer(a, newval, oldval) == (oldval))
122
123 #elif defined(__MACOSX__)
124 #include <libkern/OSAtomic.h>
125
126 #define SDL_AtomicSet(a, v) \
127 ({ \
128 int oldvalue; \
129 \
130 do { \
131 oldvalue = (a)->value; \
132 } while (!OSAtomicCompareAndSwap32Barrier(oldvalue, v, &(a)->value)); \
133 \
134 oldvalue; \
135 })
136 #define SDL_AtomicGet(a) ((a)->value)
137 #define SDL_AtomicAdd(a, v) \
138 ({ \
139 int oldvalue; \
140 \
141 do { \
142 oldvalue = (a)->value; \
143 } while (!OSAtomicCompareAndSwap32Barrier(oldvalue, oldvalue+v, &(a)->value)); \
144 \
145 oldvalue; \
146 })
147 #define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier(oldval, newval, &(a)->value)
148 #define SDL_AtomicSetPtr(a, v) (*(a) = v, OSMemoryBarrier())
149 #define SDL_AtomicGetPtr(a) (*(a))
150 #if SIZEOF_VOIDP == 4
151 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a))
152 #elif SIZEOF_VOIDP == 8
153 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a))
154 #endif
155
156 #elif defined(HAVE_GCC_ATOMICS)
157
158 #define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v)
159 #define SDL_AtomicGet(a) ((a)->value)
160 #define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v)
161 #define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval)
162 #define SDL_AtomicSetPtr(a, v) (*(a) = v, __sync_synchronize())
163 #define SDL_AtomicGetPtr(a) (*(a))
164 #define SDL_AtomicCASPtr(a, oldval, newval) __sync_bool_compare_and_swap(a, oldval, newval)
165
166 #endif
112 167
113 /** 168 /**
114 * \brief A type representing an atomic integer value. It is a struct 169 * \brief A type representing an atomic integer value. It is a struct
115 * so people don't accidentally use numeric operations on it. 170 * so people don't accidentally use numeric operations on it.
116 */ 171 */
161 #endif 216 #endif
162 217
163 /** 218 /**
164 * \brief Set an atomic variable to a new value if it is currently an old value. 219 * \brief Set an atomic variable to a new value if it is currently an old value.
165 * 220 *
166 * \return The previous value of the atomic variable 221 * \return SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
167 * 222 *
168 * \note If you don't know what this function is for, you shouldn't use it! 223 * \note If you don't know what this function is for, you shouldn't use it!
169 */ 224 */
170 #ifndef SDL_AtomicCAS 225 #ifndef SDL_AtomicCAS
171 extern DECLSPEC int SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval); 226 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
172 #endif 227 #endif
173 228
174 /** 229 /**
175 * \brief Set a pointer to a value atomically. 230 * \brief Set a pointer to a value atomically.
176 */ 231 */
186 #endif 241 #endif
187 242
188 /** 243 /**
189 * \brief Set a pointer to a new value if it is currently an old value. 244 * \brief Set a pointer to a new value if it is currently an old value.
190 * 245 *
191 * \return The previous value of the pointer 246 * \return SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
192 * 247 *
193 * \note If you don't know what this function is for, you shouldn't use it! 248 * \note If you don't know what this function is for, you shouldn't use it!
194 */ 249 */
195 #ifndef SDL_AtomicCASPtr 250 #ifndef SDL_AtomicCASPtr
196 extern DECLSPEC void* SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval); 251 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
197 #endif 252 #endif
198 253
199 /* Ends C function definitions when using C++ */ 254 /* Ends C function definitions when using C++ */
200 #ifdef __cplusplus 255 #ifdef __cplusplus
201 /* *INDENT-OFF* */ 256 /* *INDENT-OFF* */