/** * Copyright (C) 2021 Saturneric * * This file is part of GpgFrontend. * * GpgFrontend is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GpgFrontend is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GpgFrontend. If not, see . * * The initial version of the source code is inherited from * the gpg4usb project, which is under GPL-3.0-or-later. * * All the source code of GpgFrontend was modified and released by * Saturneric starting on May 12, 2021. * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #include "GpgConstants.h" namespace GpgFrontend { /** * @brief object which in channel system * */ class GPGFRONTEND_CORE_EXPORT ChannelObject { public: /** * @brief Construct a new Default Channel Object object * */ ChannelObject() noexcept; /** * @brief Construct a new Channel Object object * * @param channel */ ChannelObject(int channel); /** * @brief Get the Default Channel object * * @return int */ static int GetDefaultChannel(); /** * @brief Get the Channel object * * @return int */ [[nodiscard]] int GetChannel() const; /** * @brief Set the Channel object * * @param channel */ void SetChannel(int channel); private: int channel_ = _default_channel; ///< The channel id static constexpr int _default_channel = 0; ///< The default channel id }; class GPGFRONTEND_CORE_EXPORT SingletonStorage { public: /** * @brief * * @param channel */ void ReleaseChannel(int channel); /** * @brief * * @param channel * @return T* */ ChannelObject* FindObjectInChannel(int channel); /** * @brief Get all the channel ids * * @return std::vector */ std::vector GetAllChannelId(); /** * @brief Set a new object in channel object * * @param channel * @param p_obj * @return T* */ ChannelObject* SetObjectInChannel(int channel, std::unique_ptr p_obj); private: std::shared_mutex instances_mutex_; ///< mutex for _instances_map std::map> instances_map_; ///< map of singleton instances }; class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection { public: /** * @brief Get the Instance object * * @return SingletonStorageCollection* */ static SingletonStorageCollection* GetInstance(); /** * @brief Get the Singleton Storage object * * @param singleton_function_object * @return SingletonStorage* */ SingletonStorage* GetSingletonStorage(const std::type_info&); private: std::shared_mutex storages_mutex_; ///< mutex for storages_map_ std::map> storages_map_; }; /** * @brief * * @tparam T */ template class SingletonFunctionObject : public ChannelObject { public: /** * @brief prohibit copy * */ SingletonFunctionObject(const SingletonFunctionObject&) = delete; /** * @brief prohibit copy * * @return SingletonFunctionObject& */ SingletonFunctionObject& operator=(const SingletonFunctionObject&) = delete; /** * @brief Get the Instance object * * @param channel * @return T& */ static T& GetInstance( int channel = GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL) { static_assert(std::is_base_of, T>::value, "T not derived from SingletonFunctionObject"); auto p_storage = SingletonStorageCollection::GetInstance()->GetSingletonStorage( typeid(T)); auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); if (_p_pbj == nullptr) { auto new_obj = std::unique_ptr(new T(channel)); return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj))); } else { return *_p_pbj; } } /** * @brief Create a Instance object * * @param channel * @param factory * @return T& */ static T& CreateInstance( int channel, std::function(void)> factory) { static_assert(std::is_base_of, T>::value, "T not derived from SingletonFunctionObject"); auto p_storage = SingletonStorageCollection::GetInstance()->GetSingletonStorage( typeid(T)); auto _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); if (_p_pbj == nullptr) { return *( T*)(p_storage->SetObjectInChannel(channel, std::move(factory()))); } else return *_p_pbj; } /** * @brief * * @param channel * @return T& */ static void ReleaseChannel(int channel) { SingletonStorageCollection::GetInstance() ->GetSingletonStorage(typeid(T)) ->ReleaseChannel(channel); } /** * @brief Get the Default Channel object * * @return int */ static int GetDefaultChannel() { return ChannelObject::GetDefaultChannel(); } /** * @brief Get the Channel object * * @return int */ [[nodiscard]] int GetChannel() const { return ChannelObject::GetChannel(); } /** * @brief Get all the channel ids * * @return std::vector */ static std::vector GetAllChannelId() { return SingletonStorageCollection::GetInstance() ->GetSingletonStorage(typeid(T)) ->GetAllChannelId(); } /** * @brief Construct a new Singleton Function Object object * */ SingletonFunctionObject(T&&) = delete; /** * @brief Construct a new Singleton Function Object object * */ SingletonFunctionObject(const T&) = delete; /** * @brief * */ void operator=(const T&) = delete; protected: /** * @brief Construct a new Singleton Function Object object * */ SingletonFunctionObject() = default; /** * @brief Construct a new Singleton Function Object object * * @param channel */ explicit SingletonFunctionObject(int channel) : ChannelObject(channel) {} /** * @brief Destroy the Singleton Function Object object * */ virtual ~SingletonFunctionObject() = default; }; } // namespace GpgFrontend #endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H