![]() |
Main Page Class Hierarchy Alphabetical List Compound List File List Compound Members
![]() |
00001 /******************************************************************************** 00002 * * 00003 * A t o m i c I n t e g e r * 00004 * * 00005 ********************************************************************************* 00006 * Copyright (C) 2006,2009 by Jeroen van der Zijp. All Rights Reserved. * 00007 ********************************************************************************* 00008 * This library is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU Lesser General Public License as published by * 00010 * the Free Software Foundation; either version 3 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public License * 00019 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00020 ********************************************************************************* 00021 * $Id: FXAtomic.h,v 1.32 2009/01/22 13:31:24 fox Exp $ * 00022 ********************************************************************************/ 00023 #ifndef FXATOMIC_H 00024 #define FXATOMIC_H 00025 00026 00027 namespace FX { 00028 00029 00030 /** 00031 * An atomically modifyable integer. 00032 */ 00033 class FXAtomicInt { 00034 private: 00035 volatile FXint val; 00036 public: 00037 00038 /// Constructs an atomic integer with a given initial value. 00039 FXAtomicInt(FXint v=0):val(v){} 00040 00041 00042 /// Assign from value 00043 FXAtomicInt& operator=(FXint v){ val=v; return *this; } 00044 00045 00046 /// Returns current value of the integer 00047 operator FXint() const { return val; } 00048 00049 00050 /// Returns current value of the integer 00051 inline FXint get() const { return val; } 00052 00053 00054 /// Set variable to v; return old value 00055 inline FXint set(FXint v){ 00056 #if defined(WIN32) 00057 return InterlockedExchange((LONG*)&val,v); 00058 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00059 FXint ret=v; 00060 __asm__ __volatile__("lock\n\t" 00061 "xchgl %0,%1\n\t" : "=r" (ret) : "m" (val), "0" (ret) : "memory"); 00062 return ret; 00063 #else 00064 FXint ret=val; 00065 val=v; 00066 return ret; 00067 #endif 00068 } 00069 00070 00071 /// If variable is equal to expect, set it to v; returns old value 00072 inline FXint cas(FXint expect,FXint v){ 00073 #if defined(WIN32) 00074 return InterlockedCompareExchange((LONG*)&val,v,expect); 00075 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00076 FXint ret; 00077 __asm__ __volatile__("lock\n\t" 00078 "cmpxchgl %1,%2\n\t" : "=a" (ret) : "r" (v), "m" (val), "0" (expect) : "memory"); 00079 return ret; 00080 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00081 return __sync_val_compare_and_swap(&val,expect,v); 00082 #else 00083 FXint ret=val; 00084 if(val==expect) val=v; 00085 return ret; 00086 #endif 00087 } 00088 00089 00090 /// Atomically add v to the variable 00091 inline FXAtomicInt& operator+=(FXint v){ 00092 #if defined(WIN32) 00093 InterlockedAdd((LONG*)&val,v); 00094 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00095 __asm__ __volatile__ ("lock\n\t" 00096 "addl %1,%0\n\t" : "=m" (val) : "ir" (v), "m" (val) : "memory"); 00097 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00098 __sync_add_and_fetch(&val,v); 00099 #else 00100 val+=v; 00101 #endif 00102 return *this; 00103 } 00104 00105 00106 /// Atomically substract v from the variable 00107 inline FXAtomicInt& operator-=(FXint v){ 00108 #if defined(WIN32) 00109 InterlockedAdd((LONG*)&val,-v); 00110 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00111 __asm__ __volatile__ ("lock\n\t" 00112 "subl %1,%0\n\t" : "=m" (val) : "ir" (v), "m" (val) : "memory"); 00113 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00114 __sync_add_and_fetch(&val,-v); 00115 #else 00116 val-=v; 00117 #endif 00118 return *this; 00119 } 00120 00121 00122 /// Atomically bitwise-or v to the variable 00123 inline FXAtomicInt& operator|=(FXint v){ 00124 #if defined(WIN32) 00125 InterlockedOr((LONG*)&val,v); 00126 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00127 __asm__ __volatile__ ("lock\n\t" 00128 "orl %1,%0\n\t" : "=m" (val) : "ir" (v), "m" (val) : "memory"); 00129 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00130 __sync_or_and_fetch(&val,v); 00131 #else 00132 val|=v; 00133 #endif 00134 return *this; 00135 } 00136 00137 00138 /// Atomically bitwise-and v to the variable 00139 inline FXAtomicInt& operator&=(FXint v){ 00140 #if defined(WIN32) 00141 InterlockedAnd((LONG*)&val,v); 00142 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00143 __sync_and_and_fetch(&val,v); 00144 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00145 __asm__ __volatile__ ("lock\n\t" 00146 "andl %1,%0\n\t" : "=m" (val) : "ir" (v), "m" (val) : "memory"); 00147 #else 00148 val&=v; 00149 #endif 00150 return *this; 00151 } 00152 00153 00154 /// Atomically bitwise-xor v to the variable 00155 inline FXAtomicInt& operator^=(FXint v){ 00156 #if defined(WIN32) 00157 InterlockedXor((LONG*)&val,v); 00158 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00159 __sync_xor_and_fetch(&val,v); 00160 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00161 __asm__ __volatile__ ("lock\n\t" 00162 "xorl %1,%0\n\t" : "=m" (val) : "ir" (v), "m" (val) : "memory"); 00163 #else 00164 val^=v; 00165 #endif 00166 return *this; 00167 } 00168 00169 00170 /// Atomically increment the integer, prefix version 00171 inline FXint operator++(){ 00172 #if defined(WIN32) 00173 return InterlockedAdd((LONG*)&val,1); 00174 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00175 FXint ret=1; 00176 __asm__ __volatile__ ("lock\n\t" 00177 "xaddl %0,%1\n\t" : "=r"(ret), "=m"(val) : "0"(ret), "m"(val) : "memory"); 00178 return ret+1; 00179 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00180 return __sync_add_and_fetch(&val,1); 00181 #else 00182 return ++val; 00183 #endif 00184 } 00185 00186 00187 /// Atomically decrement the integer, prefix version 00188 inline FXint operator--(){ 00189 #if defined(WIN32) 00190 return InterlockedAdd((LONG*)&val,-1); 00191 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00192 FXint ret=-1; 00193 __asm__ __volatile__ ("lock\n\t" 00194 "xaddl %0,%1\n\t" : "=r"(ret), "=m"(val) : "0"(ret), "m"(val) : "memory"); 00195 return ret-1; 00196 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00197 return __sync_add_and_fetch(&val,-1); 00198 #else 00199 return --val; 00200 #endif 00201 } 00202 00203 00204 /// Atomically increment value, postfix version 00205 inline int operator++(FXint){ 00206 #if defined(WIN32) 00207 return InterlockedExchangeAdd((LONG*)&val,1); 00208 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00209 FXint ret=1; 00210 __asm__ __volatile__ ("lock\n\t" 00211 "xaddl %0,%1\n\t" : "=r"(ret), "=m"(val) : "0"(ret), "m"(val) : "memory"); 00212 return ret; 00213 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00214 return __sync_fetch_and_add(&val,1); 00215 #else 00216 return val++; 00217 #endif 00218 } 00219 00220 00221 /// Atomically decrement value, postfix version 00222 inline FXint operator--(FXint){ 00223 #if defined(WIN32) 00224 return InterlockedExchangeAdd((LONG*)&val,-1); 00225 #elif (defined(__GNUC__) || defined(__ICC)) && (defined(__i386__) || defined(__x86_64__)) 00226 FXint ret=-1; 00227 __asm__ __volatile__ ("lock\n\t" 00228 "xaddl %0,%1\n\t" : "=r"(ret), "=m"(val) : "0"(ret), "m"(val) : "memory"); 00229 return ret; 00230 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00231 return __sync_fetch_and_add(&val,-1); 00232 #else 00233 return val--; 00234 #endif 00235 } 00236 }; 00237 00238 00239 00240 00241 /** 00242 * An atomically modifyable pointer. 00243 */ 00244 template<class EType> 00245 class FXAtomicPtr { 00246 private: 00247 EType *volatile ptr; 00248 public: 00249 00250 /// Constructs an atomic pointer with a given initial value. 00251 FXAtomicPtr(EType* p=NULL):ptr(p){ } 00252 00253 /// Assign from pointer 00254 FXAtomicPtr& operator=(EType *p){ ptr=p; return *this; } 00255 00256 /// Returns current value of the pointer 00257 operator EType*() const { return ptr; } 00258 00259 /// Dereference operator 00260 EType& operator*() const { return *ptr; } 00261 00262 /// Follow pointer operator 00263 EType *operator->() const { return ptr; } 00264 00265 00266 /// Returns current value of the pointer 00267 inline EType* get() const { return ptr; } 00268 00269 00270 /// Set pointer to p; return old value 00271 inline EType* set(EType* p){ 00272 #if defined(WIN32) 00273 return (EType*)InterlockedExchangePointer((void *volatile)&ptr,p); 00274 #elif (defined(__GNUC__) || defined(__ICC)) && defined(__i386__) 00275 EType* ret=p; 00276 __asm__ __volatile__("lock\n\t" 00277 "xchgl %0,%1\n\t" : "=r" (ret) : "m" (ptr), "0" (ret) : "memory"); 00278 return ret; 00279 #elif (defined(__GNUC__) || defined(__ICC)) && defined(__x86_64__) 00280 EType* ret=p; 00281 __asm__ __volatile__("lock\n\t" 00282 "xchgq %0,%1\n\t" : "=r" (ret) : "m" (ptr), "0" (ret) : "memory"); 00283 return ret; 00284 #else 00285 EType* ret=ptr; 00286 ptr=p; 00287 return ret; 00288 #endif 00289 } 00290 00291 00292 /// If pointer is equal to expect, set it to p; returns old value 00293 inline EType* cas(EType* expect,EType* p){ 00294 #if defined(WIN32) 00295 return (EType*)InterlockedCompareExchangePointer((void *volatile)&ptr,p,expect); 00296 #elif (defined(__GNUC__) || defined(__ICC)) && defined(__i386__) 00297 EType* ret; 00298 __asm__ __volatile__("lock\n\t" 00299 "cmpxchgl %1,%2\n\t" : "=a" (ret) : "r" (p), "m" (ptr), "0" (expect) : "memory"); 00300 return ret; 00301 #elif (defined(__GNUC__) || defined(__ICC)) && defined(__x86_64__) 00302 EType* ret; 00303 __asm__ __volatile__("lock\n\t" 00304 "cmpxchgq %1,%2\n\t" : "=a" (ret) : "r" (p), "m" (ptr), "0" (expect) : "memory"); 00305 return ret; 00306 #elif defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__)) 00307 return __sync_val_compare_and_swap(&ptr,expect,p); 00308 #else 00309 EType* ret=ptr; 00310 if(ptr==expect) ptr=p; 00311 return ret; 00312 #endif 00313 } 00314 }; 00315 00316 00317 } 00318 00319 #endif
![]() |