cli_volatile.hpp (3147B)
1 /* Relacy Race Detector 2 * Copyright (c) 2008-2013, Dmitry S. Vyukov 3 * All rights reserved. 4 * This software is provided AS-IS with no warranty, either express or implied. 5 * This software is distributed under a license and may not be copied, 6 * modified or distributed except as expressly authorized under the 7 * terms of the license contained in the file LICENSE in this distribution. 8 */ 9 10 #ifndef RL_CLI_VOLATILE_HPP 11 #define RL_CLI_VOLATILE_HPP 12 #ifdef _MSC_VER 13 # pragma once 14 #endif 15 16 #include "base.hpp" 17 #include "atomic.hpp" 18 19 20 //!!! fix Java volatiles! 21 // they must be modeled as seq_cst stores/loads 22 23 namespace rl 24 { 25 26 template<typename T> class nvolatile; 27 28 29 template<typename T> 30 class nvolatile_proxy 31 { 32 public: 33 typedef typename atomic_add_type<T>::type add_type; 34 template<typename Y> friend class nvolatile; 35 36 operator T () const 37 { 38 return load(); 39 } 40 41 T operator = (T value) 42 { 43 store(value); 44 return value; 45 } 46 47 T operator = (nvolatile_proxy const& r) 48 { 49 T const value = r.load(); 50 store(value); 51 return *this; 52 } 53 54 T operator ++ (int) 55 { 56 T tmp = load(); 57 store(tmp + 1); 58 return tmp; 59 } 60 61 T operator -- (int) 62 { 63 T tmp = load(); 64 store(tmp - 1); 65 return tmp; 66 } 67 68 T operator ++ () 69 { 70 T tmp = load(); 71 store(tmp + 1); 72 return tmp + 1; 73 } 74 75 T operator -- () 76 { 77 T tmp = load(); 78 store(tmp - 1); 79 return tmp - 1; 80 } 81 82 T operator += (add_type value) 83 { 84 T tmp = load(); 85 store(tmp + value); 86 return tmp + value; 87 } 88 89 T operator -= (add_type value) 90 { 91 T tmp = load(); 92 store(tmp - value); 93 return tmp - value; 94 } 95 96 private: 97 nvolatile<T>& var_; 98 debug_info info_; 99 100 nvolatile_proxy(nvolatile<T>& var, debug_info_param info) 101 : var_(var) 102 , info_(info) 103 { 104 } 105 106 T load() const 107 { 108 return var_.load(mo_acquire, info_); 109 } 110 111 void store(T value) 112 { 113 var_.store(value, mo_release, info_); 114 } 115 }; 116 117 118 119 120 template<typename T> 121 class nvolatile : public generic_atomic<T, true> 122 { 123 public: 124 typedef nvolatile_proxy<T> proxy_t; 125 friend class nvolatile_proxy<T>; 126 127 nvolatile() 128 { 129 } 130 131 explicit nvolatile(T value) 132 { 133 //??? whether here must be mo_relaxed or mo_release? 134 this->store(value, mo_release, $); 135 } 136 137 nvolatile(nvolatile const& r) 138 { 139 T const value = r.load(mo_acquire, $); 140 //??? whether here must be mo_relaxed or mo_release? 141 this->store(value, mo_release, $); 142 } 143 144 nvolatile(proxy_t const& r) 145 { 146 T const value = r.var_.load(mo_acquire, r.info_); 147 //??? whether here must be mo_relaxed or mo_release? 148 this->store(value, mo_release, r.info_); 149 } 150 151 proxy_t operator () (debug_info_param info) 152 { 153 return proxy_t(*this, info); 154 } 155 }; 156 157 158 159 } 160 161 #endif