// // Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Generic and provider-independent Variable subclasses. These variables can be // used by any state provider to implement simple variables to avoid repeat the // same common code on different state providers. #ifndef UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ #define UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_ #include #include #include "update_engine/update_manager/variable.h" namespace chromeos_update_manager { // Variable class returning a copy of a given object using the copy constructor. // This template class can be used to define variables that expose as a variable // any fixed object, such as the a provider's private member. The variable will // create copies of the provided object using the copy constructor of that // class. // // For example, a state provider exposing a private member as a variable can // implement this as follows: // // class SomethingProvider { // public: // SomethingProvider(...) { // var_something_foo = new PollCopyVariable(foo_); // } // ... // private: // MyType foo_; // }; template class PollCopyVariable : public Variable { public: // Creates the variable returning copies of the passed |ref|. The reference to // this object is kept and it should be available whenever the GetValue() // method is called. If |is_set_p| is not null, then this flag will be // consulted prior to returning the value, and an |errmsg| will be returned if // it is not set. PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p, const std::string& errmsg) : Variable(name, kVariableModePoll), ref_(ref), is_set_p_(is_set_p), errmsg_(errmsg) {} PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p) : PollCopyVariable(name, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string& name, const T& ref) : PollCopyVariable(name, ref, nullptr) {} PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, const T& ref, const bool* is_set_p, const std::string& errmsg) : Variable(name, poll_interval), ref_(ref), is_set_p_(is_set_p), errmsg_(errmsg) {} PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, const T& ref, const bool* is_set_p) : PollCopyVariable(name, poll_interval, ref, is_set_p, std::string()) {} PollCopyVariable(const std::string& name, const base::TimeDelta poll_interval, const T& ref) : PollCopyVariable(name, poll_interval, ref, nullptr) {} protected: FRIEND_TEST(UmPollCopyVariableTest, SimpleTest); FRIEND_TEST(UmPollCopyVariableTest, UseCopyConstructorTest); // Variable override. inline const T* GetValue(base::TimeDelta /* timeout */, std::string* errmsg) override { if (is_set_p_ && !(*is_set_p_)) { if (errmsg) { if (errmsg_.empty()) *errmsg = "No value set for " + this->GetName(); else *errmsg = errmsg_; } return nullptr; } return new T(ref_); } private: // Reference to the object to be copied by GetValue(). const T& ref_; // A pointer to a flag indicating whether the value is set. If null, then the // value is assumed to be set. const bool* const is_set_p_; // An error message to be returned when attempting to get an unset value. const std::string errmsg_; }; // Variable class returning a constant value that is cached on the variable when // it is created. template class ConstCopyVariable : public Variable { public: // Creates the variable returning copies of the passed |obj|. The value passed // is copied in this variable, and new copies of it will be returned by // GetValue(). ConstCopyVariable(const std::string& name, const T& obj) : Variable(name, kVariableModeConst), obj_(obj) {} protected: // Variable override. const T* GetValue(base::TimeDelta /* timeout */, std::string* /* errmsg */) override { return new T(obj_); } private: // Value to be copied by GetValue(). const T obj_; }; // Variable class returning a copy of a value returned by a given function. The // function is called every time the variable is being polled. template class CallCopyVariable : public Variable { public: CallCopyVariable(const std::string& name, base::Callback func) : Variable(name, kVariableModePoll), func_(func) {} CallCopyVariable(const std::string& name, const base::TimeDelta poll_interval, base::Callback func) : Variable(name, poll_interval), func_(func) {} protected: // Variable override. const T* GetValue(base::TimeDelta /* timeout */, std::string* /* errmsg */) override { if (func_.is_null()) return nullptr; return new T(func_.Run()); } private: FRIEND_TEST(UmCallCopyVariableTest, SimpleTest); // The function to be called, stored as a base::Callback. base::Callback func_; DISALLOW_COPY_AND_ASSIGN(CallCopyVariable); }; // A Variable class to implement simple Async variables. It provides two methods // SetValue and UnsetValue to modify the current value of the variable and // notify the registered observers whenever the value changed. // // The type T needs to be copy-constructible, default-constructible and have an // operator== (to determine if the value changed), which makes this class // suitable for basic types. template class AsyncCopyVariable : public Variable { public: explicit AsyncCopyVariable(const std::string& name) : Variable(name, kVariableModeAsync), has_value_(false) {} AsyncCopyVariable(const std::string& name, const T value) : Variable(name, kVariableModeAsync), has_value_(true), value_(value) {} void SetValue(const T& new_value) { bool should_notify = !(has_value_ && new_value == value_); value_ = new_value; has_value_ = true; if (should_notify) this->NotifyValueChanged(); } void UnsetValue() { if (has_value_) { has_value_ = false; this->NotifyValueChanged(); } } protected: // Variable override. const T* GetValue(base::TimeDelta /* timeout */, std::string* errmsg) override { if (!has_value_) { if (errmsg) *errmsg = "No value set for " + this->GetName(); return nullptr; } return new T(value_); } private: // Whether the variable has a value set. bool has_value_; // Copy of the object to be returned by GetValue(). T value_; }; } // namespace chromeos_update_manager #endif // UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_