00001 #ifndef __LDK_ATOMIC_H__
00002 #define __LDK_ATOMIC_H__
00003 #include "LDK/Types.h"
00004
00005 namespace LDK
00006 {
00007
00008 template <typename AddrT, typename OldvalT, typename NewvalT>
00009 inline bool CAS(volatile AddrT *addr, volatile OldvalT oldval, volatile NewvalT newval)
00010 {
00011 return __sync_bool_compare_and_swap(addr,oldval,newval);
00012 }
00013
00014 template
00015 <
00016 typename V1T,
00017 typename V2T
00018 >
00019 union Cas2Data
00020 {
00021 volatile uint64 m64;
00022 struct
00023 {
00024 volatile V1T m1;
00025 volatile V2T m2;
00026 }volatile m32;
00027
00028 Cas2Data(volatile V1T v1, volatile V2T v2)
00029 {
00030 m32.m1 = v1;
00031 m32.m2 = v2;
00032 }
00033 };
00034
00035
00036
00037
00038 template
00039 <
00040 typename AddrT,
00041 typename V1T,
00042 typename V2T,
00043 typename N1T,
00044 typename N2T
00045 >
00046 inline bool CAS2(volatile AddrT * addr, volatile V1T v1, volatile V2T v2, volatile N1T n1, volatile N2T n2)
00047 {
00048 Cas2Data<V1T,V2T> oldval(v1, v2);
00049 Cas2Data<N1T,N2T> newval(n1, n2);
00050 return __sync_bool_compare_and_swap(addr,oldval.m64,newval.m64);
00051 }
00052
00053 template <typename Int>
00054 class Atomic
00055 {
00056 private:
00057
00058 volatile Int mInt;
00059 bool operator==(Int rhs) { return false; }
00060
00061 public:
00062
00063 typedef Int Type;
00064
00065 inline Atomic(volatile Int rhs=0) : mInt(rhs)
00066 {}
00067 inline Atomic(const Atomic& rhs) : mInt(rhs.mInt)
00068 {}
00069 inline ~Atomic() {}
00070 inline operator bool() { return !CAS(&mInt,0,mInt); }
00071 inline volatile Int value() { return mInt; }
00072 inline volatile Int operator++()
00073 {
00074 Int val;
00075 do
00076 {
00077 val = mInt;
00078 }while(!CAS(&mInt, val, val+1));
00079 return val;
00080 }
00081 inline volatile Int operator++(int)
00082 {
00083 Int val;
00084 do
00085 {
00086 val = mInt;
00087 }while(!CAS(&mInt, val, val+1));
00088 return val;
00089 }
00090 inline volatile Int operator--()
00091 {
00092 Int val;
00093 do
00094 {
00095 val = mInt;
00096 }while(!CAS(&mInt, val, val-1));
00097 return val;
00098 }
00099 inline volatile Int operator--(int)
00100 {
00101 Int val;
00102 do
00103 {
00104 val = mInt;
00105 }while(!CAS(&mInt, val, val-1));
00106 return val;
00107 }
00108
00109 inline volatile bool equals(volatile Int rhs) { return CAS(&mInt,rhs,mInt); }
00110 friend inline volatile bool operator==(const Atomic& lhs, const Atomic& rhs) { return CAS(&lhs.mInt,rhs.mInt,lhs.mInt); }
00111
00112 inline Atomic& operator=(const Atomic& rhs)
00113 {
00114 while(!CAS(&mInt,mInt,rhs.mInt));
00115 return *this;
00116 }
00117 inline Atomic& operator=(volatile Int rhs)
00118 {
00119 while(!CAS(&mInt,mInt,rhs));
00120 return *this;
00121 }
00122
00123 inline Atomic& operator+=(const Atomic& rhs)
00124 {
00125 Int oldval;
00126 Int newval;
00127 do
00128 {
00129 oldval = mInt;
00130 newval = oldval + rhs.mInt;
00131 }while(!CAS(&mInt,oldval,newval));
00132 return *this;
00133 }
00134 inline Atomic& operator+=(volatile Int rhs)
00135 {
00136 Int oldval;
00137 Int newval;
00138 do
00139 {
00140 oldval = mInt;
00141 newval = oldval + rhs;
00142 }while(!CAS(&mInt,oldval,newval));
00143 return *this;
00144 }
00145 friend inline Atomic operator+(const Atomic& lhs, const Atomic& rhs)
00146 {
00147 return Atomic(lhs.mInt+rhs.mInt);
00148 }
00149 friend inline Atomic operator+(const Atomic& lhs, volatile Int rhs)
00150 {
00151 return Atomic(lhs.mInt+rhs);
00152 }
00153
00154 inline Atomic& operator-=(const Atomic& rhs)
00155 {
00156 Int oldval;
00157 Int newval;
00158 do
00159 {
00160 oldval = mInt;
00161 newval = oldval - rhs.mInt;
00162 }while(!CAS(&mInt,oldval,newval));
00163 return *this;
00164 }
00165 inline Atomic& operator-=(volatile Int rhs)
00166 {
00167 Int oldval;
00168 Int newval;
00169 do
00170 {
00171 oldval = mInt;
00172 newval = oldval - rhs;
00173 }while(!CAS(&mInt,oldval,newval));
00174 return *this;
00175 }
00176 friend inline Atomic operator-(const Atomic& lhs, const Atomic& rhs)
00177 {
00178 return Atomic(lhs.mInt-rhs.mInt);
00179 }
00180 friend inline Atomic operator-(const Atomic& lhs, volatile Int rhs)
00181 {
00182 return Atomic(lhs.mInt-rhs);
00183 }
00184
00185 inline Atomic& operator*=(const Atomic& rhs)
00186 {
00187 Int oldval;
00188 Int newval;
00189 do
00190 {
00191 oldval = mInt;
00192 newval = oldval * rhs.mInt;
00193 }while(!CAS(&mInt,oldval,newval));
00194 return *this;
00195 }
00196 inline Atomic& operator*=(volatile Int rhs)
00197 {
00198 Int oldval;
00199 Int newval;
00200 do
00201 {
00202 oldval = mInt;
00203 newval = oldval * rhs;
00204 }while(!CAS(&mInt,oldval,newval));
00205 return *this;
00206 }
00207 friend inline Atomic operator*(const Atomic& lhs, const Atomic& rhs)
00208 {
00209 return Atomic(lhs.mInt*rhs.mInt);
00210 }
00211 friend inline Atomic operator*(const Atomic& lhs, volatile Int rhs)
00212 {
00213 return Atomic(lhs.mInt*rhs);
00214 }
00215
00216 inline Atomic& operator/=(const Atomic& rhs)
00217 {
00218 Int oldval;
00219 Int newval;
00220 do
00221 {
00222 oldval = mInt;
00223 newval = oldval / rhs.mInt;
00224 }while(!CAS(&mInt,oldval,newval));
00225 return *this;
00226 }
00227 inline Atomic& operator/=(volatile Int rhs)
00228 {
00229 Int oldval;
00230 Int newval;
00231 do
00232 {
00233 oldval = mInt;
00234 newval = oldval / rhs;
00235 }while(!CAS(&mInt,oldval,newval));
00236 return *this;
00237 }
00238 friend inline Atomic operator/(const Atomic& lhs, const Atomic& rhs)
00239 {
00240 return Atomic(lhs.mInt/rhs.mInt);
00241 }
00242 friend inline Atomic operator/(const Atomic& lhs, volatile Int rhs)
00243 {
00244 return Atomic(lhs.mInt/rhs);
00245 }
00246
00247 inline Atomic& operator&=(const Atomic& rhs)
00248 {
00249 Int oldval;
00250 Int newval;
00251 do
00252 {
00253 oldval = mInt;
00254 newval = oldval & rhs.mInt;
00255 }while(!CAS(&mInt,oldval,newval));
00256 return *this;
00257 }
00258 inline Atomic& operator&=(volatile Int rhs)
00259 {
00260 Int oldval;
00261 Int newval;
00262 do
00263 {
00264 oldval = mInt;
00265 newval = oldval & rhs;
00266 }while(!CAS(&mInt,oldval,newval));
00267 return *this;
00268 }
00269 friend inline Atomic operator&(const Atomic& lhs, const Atomic& rhs)
00270 {
00271 return Atomic(lhs.mInt&rhs.mInt);
00272 }
00273 friend inline Atomic operator&(const Atomic& lhs, volatile Int rhs)
00274 {
00275 return Atomic(lhs.mInt&rhs);
00276 }
00277
00278 inline Atomic& operator|=(const Atomic& rhs)
00279 {
00280 Int oldval;
00281 Int newval;
00282 do
00283 {
00284 oldval = mInt;
00285 newval = oldval | rhs.mInt;
00286 }while(!CAS(&mInt,oldval,newval));
00287 return *this;
00288 }
00289 inline Atomic& operator|=(volatile Int rhs)
00290 {
00291 Int oldval;
00292 Int newval;
00293 do
00294 {
00295 oldval = mInt;
00296 newval = oldval | rhs;
00297 }while(!CAS(&mInt,oldval,newval));
00298 return *this;
00299 }
00300 friend inline Atomic operator|(const Atomic& lhs, const Atomic& rhs)
00301 {
00302 return Atomic(lhs.mInt | rhs.mInt);
00303 }
00304 friend inline Atomic operator|(const Atomic& lhs, volatile Int rhs)
00305 {
00306 return Atomic(lhs.mInt | rhs);
00307 }
00308
00309 inline Atomic& operator^=(const Atomic& rhs)
00310 {
00311 Int oldval;
00312 Int newval;
00313 do
00314 {
00315 oldval = mInt;
00316 newval = oldval ^ rhs.mInt;
00317 }while(!CAS(&mInt,oldval,newval));
00318 return *this;
00319 }
00320 inline Atomic& operator^=(volatile Int rhs)
00321 {
00322 Int oldval;
00323 Int newval;
00324 do
00325 {
00326 oldval = mInt;
00327 newval = oldval ^ rhs;
00328 }while(!CAS(&mInt,oldval,newval));
00329 return *this;
00330 }
00331 friend inline Atomic operator^(const Atomic& lhs, const Atomic& rhs)
00332 {
00333 return Atomic(lhs.mInt ^ rhs.mInt);
00334 }
00335 friend inline Atomic operator^(const Atomic& lhs, volatile Int rhs)
00336 {
00337 return Atomic(lhs.mInt ^ rhs);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 };
00371
00372 typedef Atomic<uint32> AtomicCount;
00373 }
00374 #endif //__LDK_ATOMIC_H__