/**
* 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