diff options
author | Saturneric <[email protected]> | 2023-02-18 11:07:58 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2023-02-18 11:07:58 +0000 |
commit | e71e56347f5063c424475ebafbae49cf75cd388e (patch) | |
tree | ed36e42df3090d3750f4eb717f7d510ed379c594 | |
parent | feat: improve task execute system (diff) | |
download | GpgFrontend-e71e56347f5063c424475ebafbae49cf75cd388e.tar.gz GpgFrontend-e71e56347f5063c424475ebafbae49cf75cd388e.zip |
fix: improve stability of the object-channel model
-rw-r--r-- | src/core/GpgFunctionObject.h | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/core/GpgFunctionObject.h b/src/core/GpgFunctionObject.h index 56d0ab22..9b8c2aa3 100644 --- a/src/core/GpgFunctionObject.h +++ b/src/core/GpgFunctionObject.h @@ -29,6 +29,8 @@ #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H +#include <mutex> + #include "GpgConstants.h" namespace GpgFrontend { @@ -169,16 +171,33 @@ class SingletonFunctionObject : public ChannelObject { */ static T& GetInstance( int channel = GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL) { + static std::mutex g_channel_mutex_map_lock; + static std::map<int, std::mutex> g_channel_mutex_map; + + { + std::lock_guard<std::mutex> guard(g_channel_mutex_map_lock); + if (g_channel_mutex_map.find(channel) == g_channel_mutex_map.end()) { + g_channel_mutex_map[channel]; + } + } + static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, "T not derived from SingletonFunctionObject<T>"); - auto p_storage = + auto* p_storage = SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( typeid(T)); - auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); if (_p_pbj == nullptr) { + // lock this channel + std::lock_guard<std::mutex> guard(g_channel_mutex_map[channel]); + + // double check + if ((_p_pbj = (T*)(p_storage->FindObjectInChannel(channel))) != nullptr) + return *_p_pbj; + + // do create object of this channel auto new_obj = std::unique_ptr<ChannelObject>(new T(channel)); return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj))); } else { |