00001 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_BUILDER_HPP
00002 #define BOOST_ATOMIC_DETAIL_ATOMIC_BUILDER_HPP
00003
00004
00005
00006
00007
00008
00009
00010 #include <boost/detail/endian.hpp>
00011 #include "valid_integral_types.hpp"
00012
00013 namespace boost_atomic {
00014 namespace detail {
00015 namespace atomic {
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 template<typename Base>
00026 class build_exchange : public Base {
00027 public:
00028 typedef typename Base::integral_type integral_type;
00029
00030 using Base::load;
00031 using Base::compare_exchange_weak;
00032
00033 bool compare_exchange_strong(
00034 integral_type &expected,
00035 integral_type desired,
00036 memory_order2 success_order,
00037 memory_order2 failure_order) volatile
00038 {
00039 integral_type expected_save=expected;
00040 while(true) {
00041 if (compare_exchange_weak(expected, desired, success_order, failure_order)) return true;
00042 if (expected_save!=expected) return false;
00043 expected=expected_save;
00044 }
00045 }
00046
00047 integral_type exchange(integral_type replacement, memory_order2 order=memory_order2_seq_cst) volatile
00048 {
00049 integral_type o=load(memory_order2_relaxed);
00050 do {} while(!compare_exchange_weak(o, replacement, order, memory_order2_relaxed));
00051 return o;
00052 }
00053
00054 build_exchange() {}
00055 explicit build_exchange(integral_type i) : Base(i) {}
00056 };
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 template<typename Base>
00071 class build_const_fetch_add : public Base {
00072 public:
00073 typedef typename Base::integral_type integral_type;
00074
00075 integral_type fetch_add(
00076 integral_type c,
00077 memory_order2 order=memory_order2_seq_cst) volatile
00078 {
00079 if (__builtin_constant_p(c)) {
00080 switch(c) {
00081 case -1: return fetch_dec(order);
00082 case 1: return fetch_inc(order);
00083 }
00084 }
00085 return fetch_add_var(c, order);
00086 }
00087
00088 build_const_fetch_add() {}
00089 explicit build_const_fetch_add(integral_type i) : Base(i) {}
00090 protected:
00091 using Base::fetch_add_var;
00092 using Base::fetch_inc;
00093 using Base::fetch_dec;
00094 };
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 template<typename Base>
00105 class build_fetch_add : public Base {
00106 public:
00107 typedef typename Base::integral_type integral_type;
00108
00109 using Base::compare_exchange_weak;
00110
00111 integral_type fetch_add(
00112 integral_type c, memory_order2 order=memory_order2_seq_cst) volatile
00113 {
00114 integral_type o=Base::load(memory_order2_relaxed), n;
00115 do {n=o+c;} while(!compare_exchange_weak(o, n, order, memory_order2_relaxed));
00116 return o;
00117 }
00118
00119 build_fetch_add() {}
00120 explicit build_fetch_add(integral_type i) : Base(i) {}
00121 };
00122
00123
00124
00125
00126
00127
00128
00129
00130 template<typename Base>
00131 class build_arithmeticops : public Base {
00132 public:
00133 typedef typename Base::integral_type integral_type;
00134
00135 using Base::fetch_add;
00136
00137 integral_type fetch_sub(
00138 integral_type c,
00139 memory_order2 order=memory_order2_seq_cst) volatile
00140 {
00141 return fetch_add(-c, order);
00142 }
00143
00144 build_arithmeticops() {}
00145 explicit build_arithmeticops(integral_type i) : Base(i) {}
00146 };
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 template<typename Base>
00157 class build_logicops : public Base {
00158 public:
00159 typedef typename Base::integral_type integral_type;
00160
00161 using Base::compare_exchange_weak;
00162 using Base::load;
00163
00164 integral_type fetch_and(integral_type c, memory_order2 order=memory_order2_seq_cst) volatile
00165 {
00166 integral_type o=load(memory_order2_relaxed), n;
00167 do {n=o&c;} while(!compare_exchange_weak(o, n, order, memory_order2_relaxed));
00168 return o;
00169 }
00170 integral_type fetch_or(integral_type c, memory_order2 order=memory_order2_seq_cst) volatile
00171 {
00172 integral_type o=load(memory_order2_relaxed), n;
00173 do {n=o|c;} while(!compare_exchange_weak(o, n, order, memory_order2_relaxed));
00174 return o;
00175 }
00176 integral_type fetch_xor(integral_type c, memory_order2 order=memory_order2_seq_cst) volatile
00177 {
00178 integral_type o=load(memory_order2_relaxed), n;
00179 do {n=o^c;} while(!compare_exchange_weak(o, n, order, memory_order2_relaxed));
00180 return o;
00181 }
00182
00183 build_logicops() {}
00184 build_logicops(integral_type i) : Base(i) {}
00185 };
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 template<typename Base>
00197 class build_atomic_from_minimal : public build_logicops< build_arithmeticops< build_fetch_add< build_exchange<Base> > > > {
00198 public:
00199 typedef build_logicops< build_arithmeticops< build_fetch_add< build_exchange<Base> > > > super;
00200 typedef typename super::integral_type integral_type;
00201
00202 build_atomic_from_minimal(void) {}
00203 build_atomic_from_minimal(typename super::integral_type i) : super(i) {}
00204 };
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 template<typename Base>
00221 class build_atomic_from_typical : public build_logicops< build_arithmeticops< build_const_fetch_add<Base> > > {
00222 public:
00223 typedef build_logicops< build_arithmeticops< build_const_fetch_add<Base> > > super;
00224 typedef typename super::integral_type integral_type;
00225
00226 build_atomic_from_typical(void) {}
00227 build_atomic_from_typical(typename super::integral_type i) : super(i) {}
00228 };
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 template<typename Base>
00243 class build_atomic_from_add : public build_logicops< build_arithmeticops<Base> > {
00244 public:
00245 typedef build_logicops< build_arithmeticops<Base> > super;
00246 typedef typename super::integral_type integral_type;
00247
00248 build_atomic_from_add(void) {}
00249 build_atomic_from_add(typename super::integral_type i) : super(i) {}
00250 };
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 template<typename Base>
00264 class build_atomic_from_exchange : public build_logicops< build_arithmeticops< build_fetch_add<Base> > > {
00265 public:
00266 typedef build_logicops< build_arithmeticops< build_fetch_add<Base> > > super;
00267 typedef typename super::integral_type integral_type;
00268
00269 build_atomic_from_exchange(void) {}
00270 build_atomic_from_exchange(typename super::integral_type i) : super(i) {}
00271 };
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 template<typename Base, typename Type>
00284 class build_base_from_larger_type {
00285 public:
00286 typedef Type integral_type;
00287
00288 build_base_from_larger_type() {}
00289 build_base_from_larger_type(integral_type t) {store(t, memory_order2_relaxed);}
00290
00291 integral_type load(memory_order2 order=memory_order2_seq_cst) const volatile
00292 {
00293 larger_integral_type v=get_base().load(order);
00294 return extract(v);
00295 }
00296 bool compare_exchange_weak(integral_type &expected,
00297 integral_type desired,
00298 memory_order2 success_order,
00299 memory_order2 failure_order) volatile
00300 {
00301 larger_integral_type expected_;
00302 larger_integral_type desired_;
00303
00304 expected_=get_base().load(memory_order2_relaxed);
00305 expected_=insert(expected_, expected);
00306 desired_=insert(expected_, desired);
00307 bool success=get_base().compare_exchange_weak(expected_, desired_, success_order, failure_order);
00308 expected=extract(expected_);
00309 return success;
00310 }
00311 void store(integral_type v,
00312 memory_order2 order=memory_order2_seq_cst) volatile
00313 {
00314 larger_integral_type expected, desired;
00315 expected=get_base().load(memory_order2_relaxed);
00316 do {
00317 desired=insert(expected, v);
00318 } while(!get_base().compare_exchange_weak(expected, desired, order, memory_order2_relaxed));
00319 }
00320
00321 bool is_lock_free(void)
00322 {
00323 return get_base().is_lock_free();
00324 }
00325 private:
00326 typedef typename Base::integral_type larger_integral_type;
00327
00328 const Base &get_base(void) const volatile
00329 {
00330 intptr_t address=(intptr_t)this;
00331 address&=~(sizeof(larger_integral_type)-1);
00332 return *reinterpret_cast<const Base *>(address);
00333 }
00334 Base &get_base(void) volatile
00335 {
00336 intptr_t address=(intptr_t)this;
00337 address&=~(sizeof(larger_integral_type)-1);
00338 return *reinterpret_cast<Base *>(address);
00339 }
00340 unsigned int get_offset(void) const volatile
00341 {
00342 intptr_t address=(intptr_t)this;
00343 address&=(sizeof(larger_integral_type)-1);
00344 return address;
00345 }
00346
00347 unsigned int get_shift(void) const volatile
00348 {
00349 #if defined(BOOST_LITTLE_ENDIAN)
00350 return get_offset()*8;
00351 #elif defined(BOOST_BIG_ENDIAN)
00352 return (sizeof(larger_integral_type)-sizeof(integral_type)-get_offset())*8;
00353 #else
00354 #error "Unknown endian"
00355 #endif
00356 }
00357
00358 integral_type extract(larger_integral_type v) const volatile
00359 {
00360 return v>>get_shift();
00361 }
00362
00363 larger_integral_type insert(larger_integral_type target, integral_type source) const volatile
00364 {
00365 larger_integral_type tmp=source;
00366 larger_integral_type mask=(larger_integral_type)-1;
00367
00368 mask=~(mask<<(8*sizeof(integral_type)));
00369
00370 mask=mask<<get_shift();
00371 tmp=tmp<<get_shift();
00372
00373 tmp=(tmp & mask) | (target & ~mask);
00374
00375 return tmp;
00376 }
00377
00378 integral_type i;
00379 };
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 template<typename Base, typename Type>
00391 class build_atomic_from_larger_type : public build_atomic_from_minimal< build_base_from_larger_type<Base, Type> > {
00392 public:
00393 typedef build_atomic_from_minimal< build_base_from_larger_type<Base, Type> > super;
00394
00395 typedef Type integral_type;
00396
00397 build_atomic_from_larger_type() {}
00398 build_atomic_from_larger_type(integral_type v) : super(v) {}
00399 };
00400
00401 }
00402 }
00403 }
00404
00405 #endif