1 // 2 // Copyright (C) 2014 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 // Generic and provider-independent Variable subclasses. These variables can be 18 // used by any state provider to implement simple variables to avoid repeat the 19 // same common code on different state providers. 20 21 #ifndef UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 22 #define UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 23 24 #include <string> 25 26 #include <base/callback.h> 27 28 #include "update_engine/update_manager/variable.h" 29 30 namespace chromeos_update_manager { 31 32 // Variable class returning a copy of a given object using the copy constructor. 33 // This template class can be used to define variables that expose as a variable 34 // any fixed object, such as the a provider's private member. The variable will 35 // create copies of the provided object using the copy constructor of that 36 // class. 37 // 38 // For example, a state provider exposing a private member as a variable can 39 // implement this as follows: 40 // 41 // class SomethingProvider { 42 // public: 43 // SomethingProvider(...) { 44 // var_something_foo = new PollCopyVariable<MyType>(foo_); 45 // } 46 // ... 47 // private: 48 // MyType foo_; 49 // }; 50 template <typename T> 51 class PollCopyVariable : public Variable<T> { 52 public: 53 // Creates the variable returning copies of the passed |ref|. The reference to 54 // this object is kept and it should be available whenever the GetValue() 55 // method is called. If |is_set_p| is not null, then this flag will be 56 // consulted prior to returning the value, and an |errmsg| will be returned if 57 // it is not set. PollCopyVariable(const std::string & name,const T & ref,const bool * is_set_p,const std::string & errmsg)58 PollCopyVariable(const std::string& name, 59 const T& ref, 60 const bool* is_set_p, 61 const std::string& errmsg) 62 : Variable<T>(name, kVariableModePoll), 63 ref_(ref), 64 is_set_p_(is_set_p), 65 errmsg_(errmsg) {} PollCopyVariable(const std::string & name,const T & ref,const bool * is_set_p)66 PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p) 67 : PollCopyVariable(name, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string & name,const T & ref)68 PollCopyVariable(const std::string& name, const T& ref) 69 : PollCopyVariable(name, ref, nullptr) {} 70 PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref,const bool * is_set_p,const std::string & errmsg)71 PollCopyVariable(const std::string& name, 72 const base::TimeDelta poll_interval, 73 const T& ref, 74 const bool* is_set_p, 75 const std::string& errmsg) 76 : Variable<T>(name, poll_interval), 77 ref_(ref), 78 is_set_p_(is_set_p), 79 errmsg_(errmsg) {} PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref,const bool * is_set_p)80 PollCopyVariable(const std::string& name, 81 const base::TimeDelta poll_interval, 82 const T& ref, 83 const bool* is_set_p) 84 : PollCopyVariable(name, poll_interval, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string & name,const base::TimeDelta poll_interval,const T & ref)85 PollCopyVariable(const std::string& name, 86 const base::TimeDelta poll_interval, 87 const T& ref) 88 : PollCopyVariable(name, poll_interval, ref, nullptr) {} 89 90 protected: 91 FRIEND_TEST(UmPollCopyVariableTest, SimpleTest); 92 FRIEND_TEST(UmPollCopyVariableTest, UseCopyConstructorTest); 93 94 // Variable override. GetValue(base::TimeDelta,std::string * errmsg)95 inline const T* GetValue(base::TimeDelta /* timeout */, 96 std::string* errmsg) override { 97 if (is_set_p_ && !(*is_set_p_)) { 98 if (errmsg) { 99 if (errmsg_.empty()) 100 *errmsg = "No value set for " + this->GetName(); 101 else 102 *errmsg = errmsg_; 103 } 104 return nullptr; 105 } 106 return new T(ref_); 107 } 108 109 private: 110 // Reference to the object to be copied by GetValue(). 111 const T& ref_; 112 113 // A pointer to a flag indicating whether the value is set. If null, then the 114 // value is assumed to be set. 115 const bool* const is_set_p_; 116 117 // An error message to be returned when attempting to get an unset value. 118 const std::string errmsg_; 119 }; 120 121 // Variable class returning a constant value that is cached on the variable when 122 // it is created. 123 template <typename T> 124 class ConstCopyVariable : public Variable<T> { 125 public: 126 // Creates the variable returning copies of the passed |obj|. The value passed 127 // is copied in this variable, and new copies of it will be returned by 128 // GetValue(). ConstCopyVariable(const std::string & name,const T & obj)129 ConstCopyVariable(const std::string& name, const T& obj) 130 : Variable<T>(name, kVariableModeConst), obj_(obj) {} 131 132 protected: 133 // Variable override. GetValue(base::TimeDelta,std::string *)134 const T* GetValue(base::TimeDelta /* timeout */, 135 std::string* /* errmsg */) override { 136 return new T(obj_); 137 } 138 139 private: 140 // Value to be copied by GetValue(). 141 const T obj_; 142 }; 143 144 // Variable class returning a copy of a value returned by a given function. The 145 // function is called every time the variable is being polled. 146 template <typename T> 147 class CallCopyVariable : public Variable<T> { 148 public: CallCopyVariable(const std::string & name,base::Callback<T (void)> func)149 CallCopyVariable(const std::string& name, base::Callback<T(void)> func) 150 : Variable<T>(name, kVariableModePoll), func_(func) {} CallCopyVariable(const std::string & name,const base::TimeDelta poll_interval,base::Callback<T (void)> func)151 CallCopyVariable(const std::string& name, 152 const base::TimeDelta poll_interval, 153 base::Callback<T(void)> func) 154 : Variable<T>(name, poll_interval), func_(func) {} 155 156 protected: 157 // Variable override. GetValue(base::TimeDelta,std::string *)158 const T* GetValue(base::TimeDelta /* timeout */, 159 std::string* /* errmsg */) override { 160 if (func_.is_null()) 161 return nullptr; 162 return new T(func_.Run()); 163 } 164 165 private: 166 FRIEND_TEST(UmCallCopyVariableTest, SimpleTest); 167 168 // The function to be called, stored as a base::Callback. 169 base::Callback<T(void)> func_; 170 171 DISALLOW_COPY_AND_ASSIGN(CallCopyVariable); 172 }; 173 174 // A Variable class to implement simple Async variables. It provides two methods 175 // SetValue and UnsetValue to modify the current value of the variable and 176 // notify the registered observers whenever the value changed. 177 // 178 // The type T needs to be copy-constructible, default-constructible and have an 179 // operator== (to determine if the value changed), which makes this class 180 // suitable for basic types. 181 template <typename T> 182 class AsyncCopyVariable : public Variable<T> { 183 public: AsyncCopyVariable(const std::string & name)184 explicit AsyncCopyVariable(const std::string& name) 185 : Variable<T>(name, kVariableModeAsync), has_value_(false) {} 186 AsyncCopyVariable(const std::string & name,const T value)187 AsyncCopyVariable(const std::string& name, const T value) 188 : Variable<T>(name, kVariableModeAsync), 189 has_value_(true), 190 value_(value) {} 191 SetValue(const T & new_value)192 void SetValue(const T& new_value) { 193 bool should_notify = !(has_value_ && new_value == value_); 194 value_ = new_value; 195 has_value_ = true; 196 if (should_notify) 197 this->NotifyValueChanged(); 198 } 199 UnsetValue()200 void UnsetValue() { 201 if (has_value_) { 202 has_value_ = false; 203 this->NotifyValueChanged(); 204 } 205 } 206 207 protected: 208 // Variable override. GetValue(base::TimeDelta,std::string * errmsg)209 const T* GetValue(base::TimeDelta /* timeout */, 210 std::string* errmsg) override { 211 if (!has_value_) { 212 if (errmsg) 213 *errmsg = "No value set for " + this->GetName(); 214 return nullptr; 215 } 216 return new T(value_); 217 } 218 219 private: 220 // Whether the variable has a value set. 221 bool has_value_; 222 223 // Copy of the object to be returned by GetValue(). 224 T value_; 225 }; 226 227 } // namespace chromeos_update_manager 228 229 #endif // UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ 230