diff options
author | Saturneric <[email protected]> | 2021-09-19 15:54:06 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-09-19 15:54:06 +0000 |
commit | 0f0b9510bbb8be150984bfa8af03f43e1d4135d3 (patch) | |
tree | 6436834f05ac0fe32646dbf47488d25a98ddf8fa /src/gpg/GpgFunctionObject.h | |
parent | Continue to write core test code. (diff) | |
download | GpgFrontend-0f0b9510bbb8be150984bfa8af03f43e1d4135d3.tar.gz GpgFrontend-0f0b9510bbb8be150984bfa8af03f43e1d4135d3.zip |
Support multi-channel Context.
Make the test configurable.
Other modifications.
Diffstat (limited to '')
-rw-r--r-- | src/gpg/GpgFunctionObject.h | 113 |
1 files changed, 95 insertions, 18 deletions
diff --git a/src/gpg/GpgFunctionObject.h b/src/gpg/GpgFunctionObject.h index 654f81d3..cb55cf92 100644 --- a/src/gpg/GpgFunctionObject.h +++ b/src/gpg/GpgFunctionObject.h @@ -25,44 +25,121 @@ #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H +#include <map> #include <memory> #include <mutex> +#include <shared_mutex> +#include <stdexcept> +#include <string> #include <easyloggingpp/easylogging++.h> namespace GpgFrontend { -template <typename T> class SingletonFunctionObject { -public: - static T &GetInstance() { - LOG(INFO) << "SingletonFunctionObject GetInstance Calling " - << typeid(T).name(); - std::lock_guard<std::mutex> guard(_instance_mutex); - if (_instance == nullptr) - _instance = std::make_unique<T>(); - return *_instance; + +template <typename T> +class SingletonFunctionObject { + public: + static T& GetInstance(int channel = 0) { + DLOG(INFO) << "SingletonFunctionObject GetInstance Calling " + << typeid(T).name() << " channel " << channel; + if (!channel) { + std::lock_guard<std::mutex> guard(_instance_mutex); + if (_instance == nullptr) + _instance = std::make_unique<T>(); + return *_instance; + } else { + // read _instances_map + decltype(_instances_map.end()) _it; + { + std::shared_lock lock(_instances_mutex); + _it = _instances_map.find(channel); + } + if (_it != _instances_map.end()) + return *_it->second; + else + return CreateInstance(channel); + } } - SingletonFunctionObject(T &&) = delete; + static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) { + DLOG(INFO) << "SingletonFunctionObject CreateInstance Calling " + << typeid(T).name() << " channel " << channel; + if (!channel) + return *_instance; + + // read _instances_map + decltype(_instances_map.end()) _it; + { + std::shared_lock lock(_instances_mutex); + _it = _instances_map.find(channel); + } + if (_it == _instances_map.end()) { + { + std::lock_guard<std::mutex> guard(_default_channel_mutex); + int tmp = channel; + std::swap(_default_channel, tmp); + if (p_obj == nullptr) + p_obj = std::make_unique<T>(); + std::swap(_default_channel, tmp); + } + T* obj = p_obj.get(); + + // change _instances_map + { + std::unique_lock lock(_instances_mutex); + _instances_map.insert({channel, std::move(p_obj)}); + } + return *obj; + } else { + return *_it->second; + } + } + + static int GetDefaultChannel() { return _default_channel; } + + int GetChannel() const { return channel_; } + + SingletonFunctionObject(T&&) = delete; + + SingletonFunctionObject(const T&) = delete; - SingletonFunctionObject(const T &) = delete; + void operator=(const T&) = delete; - void operator=(const T &) = delete; + protected: + SingletonFunctionObject() {} -protected: - SingletonFunctionObject() = default; + SingletonFunctionObject(int channel) : channel_(channel) {} virtual ~SingletonFunctionObject() = default; -private: + private: + int channel_ = _default_channel; + static int _default_channel; + static std::mutex _default_channel_mutex; static std::mutex _instance_mutex; + static std::shared_mutex _instances_mutex; static std::unique_ptr<T> _instance; + static std::map<int, std::unique_ptr<T>> _instances_map; }; -template <typename T> std::mutex SingletonFunctionObject<T>::_instance_mutex; +template <typename T> +int SingletonFunctionObject<T>::_default_channel = 0; + +template <typename T> +std::mutex SingletonFunctionObject<T>::_default_channel_mutex; + +template <typename T> +std::mutex SingletonFunctionObject<T>::_instance_mutex; + +template <typename T> +std::shared_mutex SingletonFunctionObject<T>::_instances_mutex; template <typename T> std::unique_ptr<T> SingletonFunctionObject<T>::_instance = nullptr; -} // namespace GpgFrontend +template <typename T> +std::map<int, std::unique_ptr<T>> SingletonFunctionObject<T>::_instances_map; + +} // namespace GpgFrontend -#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H +#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H |