// SPDX-License-Identifier: Apache-2.0 // Copyright chargebyte GmbH and Contributors to EVerest #ifndef GENERICINFOSTORE_HPP #define GENERICINFOSTORE_HPP #include #include // for std::function #include #include #include #include #include // This contains types for all the data objects namespace data { template class GenericInfoStore { protected: // the associated data store T dataobj; // protect the data object // NB: mutable in order to be able to lock the mutex in const functions mutable std::mutex data_mutex; // function to call when changes occurred std::function notification_callback; // override this if structures need special (non-default) initialization virtual void init_data(){}; // whether the non-optional values are valid, so that the RPC interface can generate an error std::atomic data_is_valid{false}; public: explicit GenericInfoStore() { this->init_data(); }; // if the returned value has no value, the data is incomplete or not available std::optional get_data() const { if (this->data_is_valid) { std::unique_lock data_lock{this->data_mutex}; return this->dataobj; } else { return std::nullopt; } } // set the data object. This method may need to be overridden with custom copy functions if the data // object is not a simple type e.g. pointers and has no copy/assignment operator // Note: all setters, also in derived classes, must use the data mutex // e.g. std::unique_lock data_lock(this->data_mutex) virtual void set_data(const T& in) { // check for changes std::unique_lock data_lock(this->data_mutex); if (in != this->dataobj) { this->dataobj = in; this->data_is_valid = true; data_lock.unlock(); // call the notification callback if it is set notify_data_changed(); } } // notify that data has changed void notify_data_changed() { std::unique_lock data_lock(this->data_mutex); if (this->notification_callback && this->data_is_valid) { // create a copy of the data object T data_copy = this->dataobj; // unlock explicitly before entering callback data_lock.unlock(); this->notification_callback(data_copy); } } // register a callback which is triggered when any data in the associated data store changes void register_notification_callback(const std::function& callback) { this->notification_callback = callback; } }; } // namespace data #endif // GENERICINFOSTORE_HPP