atomic_templates.h

00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002      Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 // -*- mode:c++; c-basic-offset:4 -*-
00025 /*<std-header orig-src='shore'>
00026 
00027  $Id: atomic_templates.h,v 1.5 2010/12/17 19:36:26 nhall Exp $
00028 
00029 SHORE -- Scalable Heterogeneous Object REpository
00030 
00031 Copyright (c) 1994-99 Computer Sciences Department, University of
00032                       Wisconsin -- Madison
00033 All Rights Reserved.
00034 
00035 Permission to use, copy, modify and distribute this software and its
00036 documentation is hereby granted, provided that both the copyright
00037 notice and this permission notice appear in all copies of the
00038 software, derivative works or modified versions, and any portions
00039 thereof, and that both notices appear in supporting documentation.
00040 
00041 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00042 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00043 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00044 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00045 
00046 This software was developed with support by the Advanced Research
00047 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00048 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00049 Further funding for this work was provided by DARPA through
00050 Rome Research Laboratory Contract No. F30602-97-2-0247.
00051 
00052 */
00053 
00054 /*
00055 * The vast majority of the atomic add instructions are for
00056 * incrementing or decrementing by one. For those, we use
00057 * atomic_inc and atomic_dec.
00058 *
00059 * For the few others, we need to be careful about the
00060 * delta argument lest we lose bits in it by silent conversion
00061 * from a 64-bit int to a 32-bit int.
00062 * For that reason, we've made templates for each delta type
00063 * and what with their unwieldy names, we might be forced to
00064 * be careful about which we use.
00065 *
00066 */
00067 
00068 #ifndef ATOMIC_TEMPLATES_H
00069 #define ATOMIC_TEMPLATES_H
00070 
00071 #include "atomic_ops.h"
00072 
00073 /* The volatile in the template might appear to be
00074  * redundant, but it allows us to use T that isn't itself volatile
00075  *
00076  * Don't be surprised if you have to expand this list of 
00077  * specializations.
00078  */
00079 
00080 template<class T>
00081 void atomic_inc(T volatile &val);
00082 template<class T>
00083 void atomic_dec(T volatile &val);
00084 
00085 template<>
00086 inline void atomic_inc(int volatile &val)
00087 { atomic_add_int( (unsigned int volatile *)&val, 1); }
00088 
00089 template<>
00090 inline void atomic_inc(unsigned int volatile &val)
00091 { atomic_add_int(&val, 1); }
00092 
00093 template<>
00094 inline void atomic_inc(unsigned long volatile &val)
00095 { atomic_add_long(&val, 1); }
00096 
00097 #if defined(ARCH_LP64)
00098 // long and long long are same size
00099 #elif defined(__GNUG__)
00100 // Needed for int8_t and uint8_t (see the w_base.h)
00101 template<>
00102 inline void atomic_inc(unsigned long long volatile &val)
00103 { atomic_add_64((volatile uint64_t *)&val, 1); }
00104 #else
00105 #error int8_t Not supported for this compiler.
00106 #endif
00107 
00108 template<>
00109 inline void atomic_dec(int volatile &val)
00110 { atomic_add_int( (unsigned int volatile *)&val, -1); }
00111 
00112 
00113 template<>
00114 inline void atomic_dec(unsigned int volatile &val)
00115 { atomic_add_int(&val, -1); }
00116 
00117 template<>
00118 inline void atomic_dec(unsigned long volatile &val)
00119 { atomic_add_long(&val, -1); }
00120 
00121 #if defined(ARCH_LP64)
00122 // long and long long are same size
00123 #elif defined(__GNUG__)
00124 // Needed for int8_t and uint8_t (see the w_base.h)
00125 template<>
00126 inline void atomic_dec(unsigned long long volatile &val)
00127 { atomic_add_64((volatile uint64_t *)&val, -1); }
00128 #else
00129 #error int8_t Not supported for this compiler.
00130 #endif
00131 
00132 template<class T>
00133 T atomic_inc_nv(T volatile &val);
00134 template<class T>
00135 T atomic_dec_nv(T volatile &val);
00136 
00137 template<>
00138 inline int atomic_inc_nv(int volatile &val)
00139 { return atomic_add_int_nv((unsigned int volatile*)&val, 1); }
00140 template<>
00141 inline unsigned int atomic_inc_nv(unsigned int volatile &val)
00142 { return atomic_add_int_nv(&val, 1); }
00143 template<>
00144 inline unsigned long atomic_inc_nv(unsigned long volatile &val)
00145 { return atomic_add_long_nv(&val, 1); }
00146 #if defined(ARCH_LP64)
00147 // long and long long are same size
00148 #elif defined(__GNUG__)
00149 // Needed for int8_t and uint8_t (see the w_base.h)
00150 inline unsigned long long atomic_inc_nv(unsigned long long volatile &val)
00151 { return atomic_add_64_nv(&val, 1); }
00152 #else
00153 #error int8_t Not supported for this compiler.
00154 #endif
00155 
00156 template<>
00157 inline int atomic_dec_nv(int volatile &val)
00158 { return atomic_add_int_nv((unsigned int volatile*)&val, -1); }
00159 template<>
00160 inline unsigned int atomic_dec_nv(unsigned int volatile &val)
00161 { return atomic_add_int_nv(&val, -1); }
00162 template<>
00163 inline unsigned long atomic_dec_nv(unsigned long volatile &val)
00164 { return atomic_add_long_nv(&val, -1); }
00165 
00166 #if defined(ARCH_LP64)
00167 // long and long long are same size
00168 #elif defined(__GNUG__)
00169 // Needed for int8_t and uint8_t (see the w_base.h)
00170 inline unsigned long long atomic_dec_nv(unsigned long long volatile &val)
00171 { return atomic_add_64_nv(&val, -1); }
00172 #else
00173 #error int8_t Not supported for this compiler.
00174 #endif
00175 
00176 
00177 /* The following templates take an int delta */
00178 
00179 template<class T>
00180 void atomic_add_int_delta(T volatile &val, int delta);
00181 
00182 template<>
00183 inline void atomic_add_int_delta(unsigned int volatile &val, int delta) 
00184 { atomic_add_int(&val, delta); }
00185 
00186 template<>
00187 inline void atomic_add_int_delta(int volatile &val, int delta) 
00188 { atomic_add_int((unsigned int volatile*)&val, delta); }
00189 
00190 template<>
00191 inline void atomic_add_int_delta(unsigned long volatile &val, int delta) 
00192 { atomic_add_long(&val, delta); }
00193 
00194 template<>
00195 inline void atomic_add_int_delta(long volatile &val, int delta) 
00196 { atomic_add_long((unsigned long volatile*)&val, delta); }
00197 
00198 #if defined(ARCH_LP64)
00199 // long and long long are same size
00200 #elif defined(__GNUG__)
00201 // Needed for int8_t and uint8_t (see the w_base.h)
00202 template<>
00203 inline void atomic_add_int_delta(unsigned long long volatile &val, int delta) 
00204 { 
00205     int64_t  deltalg=delta;
00206     atomic_add_64(&val, deltalg); 
00207 }
00208 
00209 template<>
00210 inline void atomic_add_int_delta(long long volatile &val, int delta) 
00211 { 
00212     int64_t  deltalg=delta;
00213     atomic_add_64((unsigned long long volatile *)&val, deltalg); 
00214 }
00215 #else
00216 #error int8_t Not supported for this compiler.
00217 #endif
00218 
00219 /* atomic_add_nv variants */
00220 
00221 template<class T>
00222 T atomic_add_nv_int_delta(T volatile &val, int delta);
00223 
00224 template<>
00225 inline unsigned int atomic_add_nv_int_delta(unsigned int volatile &val, int delta) 
00226 { return atomic_add_int_nv(&val, delta); }
00227 
00228 template<>
00229 inline int atomic_add_nv_int_delta(int volatile &val, int delta) 
00230 { return atomic_add_int_nv((unsigned int*) &val, delta); }
00231 
00232 template<>
00233 inline unsigned long atomic_add_nv_int_delta(unsigned long volatile &val, int delta) 
00234 { return atomic_add_long_nv(&val, delta); }
00235 
00236 template<>
00237 inline long atomic_add_nv_int_delta(long volatile &val, int delta) 
00238 { return atomic_add_long_nv((unsigned long*) &val, delta); }
00239 
00240 #if defined(ARCH_LP64)
00241 // long and long long are same size
00242 #elif defined(__GNUG__)
00243 // Needed for int8_t and uint8_t (see the w_base.h)
00244 template<>
00245 inline unsigned long long atomic_add_nv_int_delta(unsigned long long volatile &val, int delta) 
00246 { return atomic_add_64_nv(&val, delta); }
00247 
00248 template<>
00249 inline long long atomic_add_nv_int_delta(long long volatile &val, int delta) 
00250 { return atomic_add_64_nv((unsigned long long *)&val, delta); }
00251 #else
00252 #error int8_t Not supported for this compiler.
00253 #endif
00254 
00255 /* The following templates take a long delta */
00256 template<class T>
00257 void atomic_add_long_delta(T volatile &val, long delta);
00258 
00259 template<>
00260 inline void atomic_add_long_delta(unsigned int volatile &val, long delta) 
00261 { atomic_add_int(&val, delta); }
00262 
00263 template<>
00264 inline void atomic_add_long_delta(int volatile &val, long delta) 
00265 { atomic_add_int((unsigned int volatile*)&val, delta); }
00266 
00267 template<>
00268 inline void atomic_add_long_delta(unsigned long volatile &val, long delta) 
00269 { atomic_add_long(&val, delta); }
00270 
00271 template<>
00272 inline void atomic_add_long_delta(long volatile &val, long delta) 
00273 { atomic_add_long((unsigned long volatile*)&val, delta); }
00274 
00275 #if defined(ARCH_LP64)
00276 // long and long long are same size
00277 #elif defined(__GNUG__)
00278 // Needed for int8_t and uint8_t (see the w_base.h)
00279 // Needed when building for 32 bits:
00280 template<>
00281 inline void atomic_add_long_delta(unsigned long long volatile &val, long delta) 
00282 { 
00283     int64_t  deltalg=delta;
00284     atomic_add_64(&val, deltalg); 
00285 }
00286 
00287 template<>
00288 inline void atomic_add_long_delta(long long volatile &val, long delta) 
00289 { 
00290     int64_t  deltalg=delta;
00291     atomic_add_64((unsigned long long volatile *)&val, deltalg); 
00292 }
00293 #else
00294 #error int8_t Not supported for this compiler.
00295 #endif
00296 
00297 /* atomic_add_nv variants */
00298 
00299 template<class T>
00300 T atomic_add_nv_long_delta(T volatile &val, long delta);
00301 
00302 template<>
00303 inline unsigned int atomic_add_nv_long_delta(unsigned int volatile &val, long delta) 
00304 { return atomic_add_int_nv(&val, delta); }
00305 
00306 template<>
00307 inline int atomic_add_nv_long_delta(int volatile &val, long delta) 
00308 { return atomic_add_int_nv((unsigned int*) &val, delta); }
00309 
00310 template<>
00311 inline unsigned long atomic_add_nv_long_delta(unsigned long volatile &val, long delta) 
00312 { return atomic_add_long_nv(&val, delta); }
00313 
00314 template<>
00315 inline long atomic_add_nv_long_delta(long volatile &val, long delta) 
00316 { return atomic_add_long_nv((unsigned long*) &val, delta); }
00317 
00318 #if defined(ARCH_LP64)
00319 // long and long long are same size
00320 #elif defined(__GNUG__)
00321 // Needed for int8_t and uint8_t (see the w_base.h)
00322 template<>
00323 inline unsigned long long atomic_add_nv_long_delta(unsigned long long volatile &val, long delta) 
00324 { return atomic_add_64_nv(&val, delta); }
00325 
00326 template<>
00327 inline long long atomic_add_nv_long_delta(long long volatile &val, long delta) 
00328 { return atomic_add_64_nv((unsigned long long *)&val, delta); }
00329 #else
00330 #error int8_t Not supported for this compiler.
00331 #endif
00332 
00333 #endif          /*</std-footer>*/

Generated on Mon Jan 2 15:13:56 2012 for Shore Storage Manager by  doxygen 1.4.7