Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members

FXAtomic.h

Go to the documentation of this file.
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

Copyright © 1997-2009 Jeroen van der Zijp