diff options
author | saturneric <[email protected]> | 2023-12-15 13:14:17 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2023-12-15 13:14:17 +0000 |
commit | f9a49043c35e73fc2d4ffb3ed9b39c33849c43b3 (patch) | |
tree | 7e03b0b62119ff5d5dcd732ec1ccb7d2296df86d /src/core/function/basic | |
parent | fix: slove some issues on memory and intilizations (diff) | |
download | GpgFrontend-f9a49043c35e73fc2d4ffb3ed9b39c33849c43b3.tar.gz GpgFrontend-f9a49043c35e73fc2d4ffb3ed9b39c33849c43b3.zip |
fix: slove threading and memory issues
Diffstat (limited to 'src/core/function/basic')
-rw-r--r-- | src/core/function/basic/GpgFunctionObject.cpp | 78 | ||||
-rw-r--r-- | src/core/function/basic/GpgFunctionObject.h | 86 | ||||
-rw-r--r-- | src/core/function/basic/SingletonStorage.cpp | 49 |
3 files changed, 126 insertions, 87 deletions
diff --git a/src/core/function/basic/GpgFunctionObject.cpp b/src/core/function/basic/GpgFunctionObject.cpp index 242621d2..e31ff2d6 100644 --- a/src/core/function/basic/GpgFunctionObject.cpp +++ b/src/core/function/basic/GpgFunctionObject.cpp @@ -26,4 +26,80 @@ * */ -#include "GpgFunctionObject.h"
\ No newline at end of file +#include "GpgFunctionObject.h" + +#include <map> +#include <mutex> +#include <typeinfo> + +#include "function/SecureMemoryAllocator.h" +#include "function/basic/ChannelObject.h" + +struct FunctionObjectTypeLockInfo { + std::map<int, std::mutex> channel_lock_map; + std::mutex type_lock; +}; + +std::mutex g_function_object_mutex_map_lock; +std::map<size_t, FunctionObjectTypeLockInfo> g_function_object_mutex_map; + +namespace GpgFrontend { +auto GetGlobalFunctionObjectChannelLock(const std::type_info& type, int channel) + -> std::mutex& { + std::lock_guard<std::mutex> lock_guard(g_function_object_mutex_map_lock); + auto& channel_map = g_function_object_mutex_map[type.hash_code()]; + return channel_map.channel_lock_map[channel]; +} + +auto GetGlobalFunctionObjectTypeLock(const std::type_info& type) + -> std::mutex& { + std::lock_guard<std::mutex> lock_guard(g_function_object_mutex_map_lock); + auto& channel_map = g_function_object_mutex_map[type.hash_code()]; + return channel_map.type_lock; +} + +/** + * @brief Get the Instance object + * + * @param channel + * @return T& + */ +auto GetChannelObjectInstance(const std::type_info& type, int channel) + -> ChannelObject* { + SPDLOG_TRACE("try to get instance of type: {} at channel: {}", type.name(), + channel); + + // lock this channel + std::lock_guard<std::mutex> guard( + GetGlobalFunctionObjectChannelLock(type, channel)); + + auto* p_storage = + SingletonStorageCollection::GetInstance(false)->GetSingletonStorage(type); + SPDLOG_TRACE("get singleton storage result, p_storage: {}", + static_cast<void*>(p_storage)); + + auto* p_pbj = + static_cast<ChannelObject*>(p_storage->FindObjectInChannel(channel)); + SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, + static_cast<void*>(p_pbj)); + + return p_pbj; +} + +auto CreateChannelObjectInstance(const std::type_info& type, int channel, + SecureUniquePtr<ChannelObject> channel_object) + -> ChannelObject* { + // lock this channel + std::lock_guard<std::mutex> guard( + GetGlobalFunctionObjectChannelLock(type, channel)); + + auto* p_storage = + SingletonStorageCollection::GetInstance(false)->GetSingletonStorage(type); + SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, + type.name()); + + // do create object of this channel + return p_storage->SetObjectInChannel(channel, std::move(channel_object)); +} + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index afe81131..1ea352b6 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -28,14 +28,27 @@ #pragma once +#include <mutex> +#include <stdexcept> + +#include "core/GpgFrontendCoreExport.h" #include "core/function/basic/ChannelObject.h" #include "core/function/basic/SingletonStorage.h" #include "core/function/basic/SingletonStorageCollection.h" #include "core/utils/MemoryUtils.h" -#include "spdlog/spdlog.h" namespace GpgFrontend { +auto GPGFRONTEND_CORE_EXPORT GetChannelObjectInstance( + const std::type_info& type, int channel) -> ChannelObject*; + +auto GPGFRONTEND_CORE_EXPORT CreateChannelObjectInstance( + const std::type_info& type, int channel, + SecureUniquePtr<ChannelObject> channel_object) -> ChannelObject*; + +auto GPGFRONTEND_CORE_EXPORT +GetGlobalFunctionObjectTypeLock(const std::type_info& type) -> std::mutex&; + /** * @brief * @@ -66,52 +79,18 @@ class SingletonFunctionObject : public ChannelObject { */ static auto GetInstance(int channel = GpgFrontend::kGpgFrontendDefaultChannel) -> T& { - static std::mutex g_channel_mutex_map_lock; - static std::map<int, std::mutex> g_channel_mutex_map; - - SPDLOG_TRACE("try to get instance of type: {} at channel: {}", - typeid(T).name(), channel); - - { - 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_v<SingletonFunctionObject<T>, T>, "T not derived from SingletonFunctionObject<T>"); - auto* p_storage = - SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( - typeid(T)); - SPDLOG_TRACE("get singleton storage result, p_storage: {}", - static_cast<void*>(p_storage)); - - auto* p_pbj = static_cast<T*>(p_storage->FindObjectInChannel(channel)); - SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, - static_cast<void*>(p_pbj)); - - if (p_pbj == nullptr) { - SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, - typeid(T).name()); - - // lock this channel - std::lock_guard<std::mutex> guard(g_channel_mutex_map[channel]); - - // double check - if (p_pbj = static_cast<T*>(p_storage->FindObjectInChannel(channel)); - p_pbj != nullptr) { - return *p_pbj; - } - - // do create object of this channel - auto new_obj = - ConvertToChannelObjectPtr<>(SecureCreateUniqueObject<T>(channel)); - return *static_cast<T*>( - p_storage->SetObjectInChannel(channel, std::move(new_obj))); + const auto& type = typeid(T); + std::lock_guard<std::mutex> guard(GetGlobalFunctionObjectTypeLock(type)); + auto* channel_object = GetChannelObjectInstance(type, channel); + if (channel_object == nullptr) { + channel_object = CreateChannelObjectInstance( + type, channel, + ConvertToChannelObjectPtr(SecureCreateUniqueObject<T>(channel))); } - return *p_pbj; + return *static_cast<T*>(channel_object); } /** @@ -126,23 +105,10 @@ class SingletonFunctionObject : public ChannelObject { static_assert(std::is_base_of_v<SingletonFunctionObject<T>, T>, "T not derived from SingletonFunctionObject<T>"); - auto* p_storage = - SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( - typeid(T)); - SPDLOG_TRACE("get singleton storage result, p_storage: {}", - static_cast<void*>(p_storage)); - - auto p_pbj = static_cast<T*>(p_storage->FindObjectInChannel(channel)); - SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, - static_cast<void*>(p_pbj)); - - if (p_pbj == nullptr) { - SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, - typeid(T).name()); - return *static_cast<T*>( - p_storage->SetObjectInChannel(channel, factory())); - } - return *p_pbj; + const auto& type = typeid(T); + std::lock_guard<std::mutex> guard(GetGlobalFunctionObjectTypeLock(type)); + return *static_cast<T*>( + CreateChannelObjectInstance(type, channel, factory())); } /** diff --git a/src/core/function/basic/SingletonStorage.cpp b/src/core/function/basic/SingletonStorage.cpp index 4786ad93..73e19ddd 100644 --- a/src/core/function/basic/SingletonStorage.cpp +++ b/src/core/function/basic/SingletonStorage.cpp @@ -52,7 +52,7 @@ class SingletonStorage::Impl { std::shared_lock<std::shared_mutex> lock(instances_mutex_); ins_it = instances_map_.find(channel); if (ins_it == instances_map_.end()) { - SPDLOG_TRACE("cannot find channel object, channel :{}", channel); + SPDLOG_TRACE("cannot find channel object, channel: {}", channel); return nullptr; } return ins_it->second.get(); @@ -70,35 +70,32 @@ class SingletonStorage::Impl { auto SetObjectInChannel(int channel, ChannelObjectPtr p_obj) -> GpgFrontend::ChannelObject* { - { - SPDLOG_TRACE("set channel object, type: {} in channel: {}, address: {}", - typeid(p_obj.get()).name(), channel, - static_cast<void*>(p_obj.get())); - - assert(p_obj != nullptr); - if (p_obj == nullptr) { - SPDLOG_ERROR("cannot set a nullptr as a channel obejct of channel: {}", - channel); - return nullptr; - } - - p_obj->SetChannel(channel); - auto* raw_obj = p_obj.get(); + SPDLOG_TRACE("set channel object, type: {} in channel: {}, address: {}", + typeid(p_obj.get()).name(), channel, + static_cast<void*>(p_obj.get())); + + assert(p_obj != nullptr); + if (p_obj == nullptr) { + SPDLOG_ERROR("cannot set a nullptr as a channel obejct of channel: {}", + channel); + return nullptr; + } - { - SPDLOG_TRACE( - "register channel object to instances map, " - "channel: {}, address: {}", - channel, static_cast<void*>(p_obj.get())); - std::unique_lock<std::shared_mutex> lock(instances_mutex_); - instances_map_[channel] = std::move(p_obj); - } + p_obj->SetChannel(channel); + auto* raw_obj = p_obj.get(); + { SPDLOG_TRACE( - "set channel: {} success, current channel object address: {}", - channel, static_cast<void*>(raw_obj)); - return raw_obj; + "register channel object to instances map, " + "channel: {}, address: {}", + channel, static_cast<void*>(p_obj.get())); + std::unique_lock<std::shared_mutex> lock(instances_mutex_); + instances_map_[channel] = std::move(p_obj); } + + SPDLOG_TRACE("set channel: {} success, current channel object address: {}", + channel, static_cast<void*>(raw_obj)); + return raw_obj; } private: |