00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <spl/Environment.h>
00024 #include <spl/threading/InterlockCounter.h>
00025 #include <spl/threading/Thread.h>
00026
00027 #ifdef _WINDOWS
00028
00029 #include <spl/cleanwindows.h>
00030
00031 int32 atomic_increment(volatile int32 *ptr)
00032 {
00033 int32 r = InterlockedIncrement((LONG *)ptr);
00034
00035 return r;
00036 }
00037
00038 int32 atomic_decrement(volatile int32 *ptr)
00039 {
00040 int32 r = InterlockedDecrement((LONG *)ptr);
00041
00042 return r;
00043 }
00044
00045 int32 atomic_set(volatile int32 *ptr, int32 val)
00046 {
00047 *ptr = val;
00048
00049 return val;
00050 }
00051
00052 int32 atomic_add(volatile const int32 *ptr, int32 val)
00053 {
00054 int32 r = InterlockedExchangeAdd((LONG *)ptr, val);
00055
00056 return r;
00057 }
00058
00059 int32 atomic_cas(volatile int32 *ptr, int32 val, int32 cmp)
00060 {
00061 #if _MSC_VER > 1200
00062 return InterlockedCompareExchange((volatile LONG *)ptr, val, cmp);
00063 #else
00064 return *(int32 *)InterlockedCompareExchange((void **)&ptr, &val, &cmp);
00065 #endif
00066 }
00067
00068 int32 atomic_swap(volatile int32 *ptr, int32 val)
00069 {
00070 return InterlockedExchange((LONG *)ptr, val);
00071 }
00072 #else
00073
00074 static pthread_mutex_t __atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
00075
00076 int32 atomic_increment(volatile int32 *ptr)
00077 {
00078 int32 r;
00079
00080 if (0 != pthread_mutex_lock(&__atomic_mutex))
00081 {
00082 throw new IOException(Environment::LastErrorMessage());
00083 }
00084
00085 r = ++(*ptr);
00086
00087 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00088 {
00089 throw new IOException(Environment::LastErrorMessage());
00090 }
00091
00092 return r;
00093 }
00094
00095 int32 atomic_decrement(volatile int32 *ptr)
00096 {
00097 int32 r;
00098
00099 if (0 != pthread_mutex_lock(&__atomic_mutex))
00100 {
00101 throw new IOException(Environment::LastErrorMessage());
00102 }
00103
00104 r = --(*ptr);
00105
00106 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00107 {
00108 throw new IOException(Environment::LastErrorMessage());
00109 }
00110
00111 return r;
00112 }
00113
00114 int32 atomic_set(volatile int32 *ptr, int32 val)
00115 {
00116 if ( 0 != pthread_mutex_lock(&__atomic_mutex))
00117 {
00118 throw new IOException(Environment::LastErrorMessage());
00119 }
00120
00121 (*ptr) = val;
00122
00123 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00124 {
00125 throw new IOException(Environment::LastErrorMessage());
00126 }
00127
00128 return val;
00129 }
00130
00131 int32 atomic_add(volatile int32 *ptr, int32 val)
00132 {
00133 int32 r;
00134
00135 if (0 != pthread_mutex_lock(&__atomic_mutex))
00136 {
00137 throw new IOException(Environment::LastErrorMessage());
00138 }
00139
00140 r = ((*ptr) += val);
00141
00142 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00143 {
00144 throw new IOException(Environment::LastErrorMessage());
00145 }
00146
00147 return r;
00148 }
00149
00150 int32 atomic_get(volatile const int32 *ptr)
00151 {
00152 int32 r;
00153
00154 if (0 != pthread_mutex_lock(&__atomic_mutex))
00155 {
00156 throw new IOException(Environment::LastErrorMessage());
00157 }
00158
00159 r = *ptr;
00160
00161 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00162 {
00163 throw new IOException(Environment::LastErrorMessage());
00164 }
00165
00166 return r;
00167 }
00168
00169 int32 atomic_cas(volatile int32 *ptr, int32 val, int32 cmp)
00170 {
00171 int32 r;
00172
00173 if (0 != pthread_mutex_lock(&__atomic_mutex))
00174 {
00175 throw new IOException(Environment::LastErrorMessage());
00176 }
00177
00178 r = *ptr;
00179
00180 if((*ptr) == cmp)
00181 *ptr = val;
00182
00183 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00184 {
00185 throw new IOException(Environment::LastErrorMessage());
00186 }
00187
00188 return r;
00189 }
00190
00191 int32 atomic_swap(volatile int32 *ptr, int32 val)
00192 {
00193 int32 r;
00194
00195 if (0 != pthread_mutex_lock(&__atomic_mutex))
00196 {
00197 throw new IOException(Environment::LastErrorMessage());
00198 }
00199
00200 r = *ptr;
00201 *ptr = val;
00202
00203 if (0 != pthread_mutex_unlock(&__atomic_mutex))
00204 {
00205 throw new IOException(Environment::LastErrorMessage());
00206 }
00207
00208 return r;
00209 }
00210
00211 #endif
00212
00213 InterlockCounter::InterlockCounter(int32 value ) throw()
00214 {
00215 operator=(value);
00216 }
00217
00218
00219
00220
00221 InterlockCounter::~InterlockCounter() throw()
00222 {
00223 }
00224
00225
00226
00227
00228 int32 InterlockCounter::operator++() throw()
00229 {
00230
00231 return atomic_increment(&_atomic);
00232 }
00233
00234
00235
00236
00237 int32 InterlockCounter::operator++(int) throw()
00238 {
00239
00240 int32 r = atomic_increment(&_atomic);
00241 return --r;
00242 }
00243
00244
00245
00246
00247 int32 InterlockCounter::operator--() throw()
00248 {
00249
00250 return atomic_decrement(&_atomic);
00251 }
00252
00253
00254
00255
00256 int32 InterlockCounter::operator--(int) throw()
00257 {
00258
00259 int32 r = atomic_decrement(&_atomic);
00260 return ++r;
00261 }
00262
00263
00264
00265
00266 int32 InterlockCounter::operator+=(int32 delta) throw()
00267 {
00268 return atomic_add(&_atomic, delta);
00269 }
00270
00271
00272
00273
00274 int32 InterlockCounter::operator-=(int32 delta) throw()
00275 {
00276 return atomic_add(&_atomic, -delta);
00277 }
00278
00279
00280
00281
00282 int32 InterlockCounter::operator+(int32 delta) const throw()
00283 {
00284 return Get() + delta;
00285 }
00286
00287
00288
00289
00290 int32 InterlockCounter::operator-(int32 delta) const throw()
00291 {
00292 return Get() - delta;
00293 }
00294
00295
00296
00297
00298 int32 InterlockCounter::operator=(int32 value) throw()
00299 {
00300 atomic_set(&_atomic, value);
00301
00302 return value;
00303 }
00304
00305
00306
00307
00308 int32 InterlockCounter::Set(int32 value) throw()
00309 {
00310 return atomic_set(&_atomic, value);
00311 }
00312
00313
00314
00315
00316 int32 InterlockCounter::Get() const throw()
00317 {
00318 #ifdef WIN32
00319 return(atomic_add(&_atomic, 0));
00320 #else
00321 return atomic_get(&_atomic);
00322 #endif
00323 }
00324
00325
00326
00327
00328 int32 InterlockCounter::Swap(int32 value) throw()
00329 {
00330 return atomic_swap(&_atomic, value);
00331 }
00332
00333
00334
00335
00336 int32 InterlockCounter::TestAndSet(int32 value, int32 comparand) throw()
00337 {
00338 return atomic_cas(&_atomic, value, comparand);
00339 }
00340
00341
00342
00343
00344 InterlockCounter::InterlockCounter(const InterlockCounter& other) throw()
00345 {
00346 Set(other.Get());
00347 }
00348
00349
00350
00351
00352 InterlockCounter& InterlockCounter::operator=(const InterlockCounter& other) throw()
00353 {
00354 Set(other.Get());
00355
00356 return *this;
00357 }