00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef ATOMIC_H
00031 #define ATOMIC_H
00032
00033 #include "acedia_config.hpp"
00034 #include <boost/cstdint.hpp>
00035
00042 #if defined(ACEDIA_MACOS)
00043 # define ACEDIA_MEMORY_BARRIER() OSMemoryBarrier()
00044 #elif defined(ACEDIA_LINUX)
00045 # define ACEDIA_MEMORY_BARRIER() __sync_synchronize()
00046 #elif defined(ACEDIA_WINDOWS)
00047 # define ACEDIA_MEMORY_BARRIER() MemoryBarrier()
00048 #endif
00049
00050
00051 namespace acedia
00052 {
00053 namespace atomic
00054 {
00065 template<typename T>
00066 inline bool compareAndSwap(T * volatile *ptr, T *expectedValue, T *newValue) throw();
00067
00071 inline bool compareAndSwap(volatile boost::int32_t *ptr, boost::int32_t expectedValue, boost::int32_t newValue) throw();
00072
00076 inline bool compareAndSwap(volatile boost::uint32_t *ptr, boost::uint32_t expectedValue, boost::uint32_t newValue) throw()
00077 { return compareAndSwap((boost::int32_t*) ptr, (boost::int32_t) expectedValue, (boost::int32_t) newValue); }
00078
00082 inline boost::int32_t addAndFetch(volatile boost::int32_t *ptr, boost::int32_t value) throw();
00083
00087 inline boost::uint32_t addAndFetch(volatile boost::uint32_t *ptr, boost::uint32_t value) throw()
00088 { return addAndFetch((boost::int32_t*) ptr, (boost::int32_t) value); }
00089
00090 }
00091 }
00092
00093 #if defined(ACEDIA_MACOS)
00094
00095 #include <libkern/OSAtomic.h>
00096
00097 namespace acedia
00098 {
00099 namespace atomic
00100 {
00101 template<typename T>
00102 inline bool compareAndSwap(volatile T **ptr, T *expectedValue, T *newValue) throw()
00103 { return OSAtomicCompareAndSwapPtr((void*) expectedValue, (void*) newValue, (void* volatile*) ptr); }
00104
00105 inline bool compareAndSwap(volatile boost::int32_t *ptr, boost::int32_t expectedValue, boost::int32_t newValue) throw()
00106 { return OSAtomicCompareAndSwap32(expectedValue, newValue, ptr); }
00107
00108 inline boost::int32_t addAndFetch(volatile boost::int32_t *ptr, boost::int32_t value) throw()
00109 { return OSAtomicAdd32(value, ptr); }
00110 }
00111 }
00112
00113 #elif defined(ACEDIA_LINUX)
00114
00115 namespace acedia
00116 {
00117 namespace atomic
00118 {
00119 template<typename T>
00120 inline bool compareAndSwap(volatile T **ptr, T *expectedValue, T *newValue) throw()
00121 { return __sync_bool_compare_and_swap(ptr, expectedValue, newValue); }
00122
00123 inline bool compareAndSwap(volatile boost::int32_t *ptr, boost::int32_t expectedValue, boost::int32_t newValue) throw()
00124 { return __sync_bool_compare_and_swap(ptr, expectedValue, newValue); }
00125
00126 inline boost::int32_t addAndFetch(volatile boost::int32_t *ptr, boost::int32_t value) throw()
00127 { return __sync_add_and_fetch(ptr, value); }
00128 }
00129 }
00130
00131 #elif defined(ACEDIA_WINDOWS)
00132
00133 #include <Winsock2.h>
00134 #include <Windows.h>
00135
00136 namespace acedia
00137 {
00138 namespace atomic
00139 {
00140 template<typename T>
00141 inline bool compareAndSwap(volatile T **ptr, T *expectedValue, T *newValue) throw()
00142 {
00143 return expectedValue == InterlockedCompareExchangePointer((PVOID volatile *) ptr, (PVOID) newValue, (PVOID) expectedValue);
00144 }
00145
00146 inline bool compareAndSwap(volatile boost::int32_t *ptr, boost::int32_t expectedValue, boost::int32_t newValue) throw()
00147 { return expectedValue == InterlockedCompareExchange(ptr, newValue, expectedValue); }
00148
00149 inline boost::int32_t addAndFetch(volatile boost::int32_t *ptr, boost::int32_t value) throw()
00150 {
00151 for (;;)
00152 {
00153 boost::int32_t v = *ptr;
00154 if (compareAndSwap(ptr, v, v + value))
00155 return v + value;
00156
00157 }
00158 }
00159 }
00160 }
00161
00162 #endif
00163
00164 #endif // ATOMIC_H