Atomic.h

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 //this won't work at all as intended on 64-bit :( That would require a 128 bit CAS
00035 //It's not used in atomic types themselves at least.
00036 
00037 //__int128_t on amd64
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     //might not need cas for these... hmmm
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     inline Atomic& operator~=(const Atomic& rhs)
00341     {
00342         Int oldval;
00343         Int newval;
00344         do
00345         {
00346             oldval = mInt;
00347             newval = oldval ~ rhs.mInt;
00348         }while(!CAS(&mInt,oldval,newval));
00349         return *this;
00350     }
00351     inline Atomic& operator~=(volatile Int rhs)
00352     {
00353         Int oldval;
00354         Int newval;
00355         do
00356         {
00357             oldval = mInt;
00358             newval = oldval ~ rhs;
00359         }while(!CAS(&mInt,oldval,newval));
00360         return *this;
00361     }
00362     friend inline Atomic operator~(const Atomic& lhs, const Atomic& rhs)
00363     {
00364         return Atomic(lhs.mInt ~ rhs.mInt);
00365     }
00366     friend inline Atomic operator~(const Atomic& lhs, volatile Int rhs)
00367     {
00368         return Atomic(lhs.mInt ~ rhs);
00369     }*/
00370 };
00371 
00372 typedef Atomic<uint32> AtomicCount;
00373 } //namespace LDK
00374 #endif //__LDK_ATOMIC_H__

Generated on Fri Aug 17 18:32:26 2007 for LDK by  doxygen 1.5.1