From 0251f35c93e3f0e0a6853a50fb5bd82c1b9e4187 Mon Sep 17 00:00:00 2001 From: saturneric Date: Mon, 6 Nov 2023 17:17:47 +0800 Subject: refactor: clean up core's codes --- src/core/function/basic/GpgFunctionObject.h | 209 ++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/core/function/basic/GpgFunctionObject.h (limited to 'src/core/function/basic/GpgFunctionObject.h') diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h new file mode 100644 index 00000000..59bc5715 --- /dev/null +++ b/src/core/function/basic/GpgFunctionObject.h @@ -0,0 +1,209 @@ +/** + * 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 + * + */ + +#pragma once + +#include "core/function/basic/ChannelObject.h" +#include "core/function/basic/SingletonStorage.h" +#include "core/function/basic/SingletonStorageCollection.h" + +namespace GpgFrontend { + +/** + * @brief + * + * @tparam T + */ +template +class SingletonFunctionObject : public ChannelObject { + public: + /** + * @brief prohibit copy + * + */ + SingletonFunctionObject(const SingletonFunctionObject&) = delete; + + /** + * @brief prohibit copy + * + * @return SingletonFunctionObject& + */ + auto operator=(const SingletonFunctionObject&) + -> SingletonFunctionObject& = delete; + + /** + * @brief Get the Instance object + * + * @param channel + * @return T& + */ + static auto GetInstance(int channel = GpgFrontend::kGpgfrontendDefaultChannel) + -> T& { + static std::mutex g_channel_mutex_map_lock; + static std::map g_channel_mutex_map; + + { + std::lock_guard 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, T>::value, + "T not derived from SingletonFunctionObject"); + + auto* p_storage = + SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( + typeid(T)); + auto* p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); + + if (p_pbj == nullptr) { + // lock this channel + std::lock_guard guard(g_channel_mutex_map[channel]); + + // double check + if (p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); + p_pbj != nullptr) { + return *p_pbj; + } + + // do create object of this channel + auto new_obj = std::unique_ptr(new T(channel)); + return *static_cast( + p_storage->SetObjectInChannel(channel, std::move(new_obj))); + } + return *p_pbj; + } + + /** + * @brief Create a Instance object + * + * @param channel + * @param factory + * @return T& + */ + static auto CreateInstance( + int channel, + const std::function(void)>& factory) + -> T& { + static_assert(std::is_base_of, T>::value, + "T not derived from SingletonFunctionObject"); + + auto* p_storage = + SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( + typeid(T)); + + auto p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); + + if (p_pbj == nullptr) { + return *static_cast( + p_storage->SetObjectInChannel(channel, factory())); + } + return *p_pbj; + } + + /** + * @brief + * + * @param channel + * @return T& + */ + static void ReleaseChannel(int channel) { + SingletonStorageCollection::GetInstance(false) + ->GetSingletonStorage(typeid(T)) + ->ReleaseChannel(channel); + } + + /** + * @brief Get the Default Channel object + * + * @return int + */ + static auto GetDefaultChannel() -> int { + return ChannelObject::GetDefaultChannel(); + } + + /** + * @brief Get the Channel object + * + * @return int + */ + [[nodiscard]] auto GetChannel() const -> int { + return ChannelObject::GetChannel(); + } + + /** + * @brief Get all the channel ids + * + * @return std::vector + */ + static auto GetAllChannelId() -> std::vector { + return SingletonStorageCollection::GetInstance(false) + ->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 -- cgit v1.2.3 From ae2717c3787a34a2c60d6aeef2d0b8bb8e551a1e Mon Sep 17 00:00:00 2001 From: saturneric Date: Sun, 3 Dec 2023 04:27:47 -0800 Subject: feat: improve memory security of function framework --- src/core/function/basic/GpgFunctionObject.h | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/core/function/basic/GpgFunctionObject.h') diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index 59bc5715..ec0cebac 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -31,6 +31,8 @@ #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 { @@ -67,6 +69,9 @@ class SingletonFunctionObject : public ChannelObject { static std::mutex g_channel_mutex_map_lock; static std::map g_channel_mutex_map; + SPDLOG_TRACE("try to get instance of type: {} at channel: {}", + typeid(T).name(), channel); + { std::lock_guard guard(g_channel_mutex_map_lock); if (g_channel_mutex_map.find(channel) == g_channel_mutex_map.end()) { @@ -80,9 +85,17 @@ class SingletonFunctionObject : public ChannelObject { auto* p_storage = SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( typeid(T)); + SPDLOG_TRACE("get singleton storage result, p_storage: {}", + static_cast(p_storage)); + auto* p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); + SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, + static_cast(p_pbj)); if (p_pbj == nullptr) { + SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, + typeid(T).name()); + // lock this channel std::lock_guard guard(g_channel_mutex_map[channel]); @@ -93,7 +106,8 @@ class SingletonFunctionObject : public ChannelObject { } // do create object of this channel - auto new_obj = std::unique_ptr(new T(channel)); + auto new_obj = + ConvertToChannelObjectPtr<>(SecureCreateUniqueObject(channel)); return *static_cast( p_storage->SetObjectInChannel(channel, std::move(new_obj))); } @@ -108,19 +122,23 @@ class SingletonFunctionObject : public ChannelObject { * @return T& */ static auto CreateInstance( - int channel, - const std::function(void)>& factory) - -> T& { + int channel, const std::function& factory) -> T& { static_assert(std::is_base_of, T>::value, "T not derived from SingletonFunctionObject"); auto* p_storage = SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( typeid(T)); + SPDLOG_TRACE("get singleton storage result, p_storage: {}", + static_cast(p_storage)); auto p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); + SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, + static_cast(p_pbj)); if (p_pbj == nullptr) { + SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, + typeid(T).name()); return *static_cast( p_storage->SetObjectInChannel(channel, factory())); } -- cgit v1.2.3 From 054e6e28cca2517dda2319ef683314b3318c39a6 Mon Sep 17 00:00:00 2001 From: saturneric Date: Sun, 3 Dec 2023 12:25:21 -0800 Subject: feat: standarized and speed up app env loading process --- src/core/function/basic/GpgFunctionObject.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/function/basic/GpgFunctionObject.h') diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index ec0cebac..619cad04 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -79,7 +79,7 @@ class SingletonFunctionObject : public ChannelObject { } } - static_assert(std::is_base_of, T>::value, + static_assert(std::is_base_of_v, T>, "T not derived from SingletonFunctionObject"); auto* p_storage = @@ -123,7 +123,7 @@ class SingletonFunctionObject : public ChannelObject { */ static auto CreateInstance( int channel, const std::function& factory) -> T& { - static_assert(std::is_base_of, T>::value, + static_assert(std::is_base_of_v, T>, "T not derived from SingletonFunctionObject"); auto* p_storage = -- cgit v1.2.3 From a0f0fd98efa12ef33959badcc25ff568e8b242b4 Mon Sep 17 00:00:00 2001 From: saturneric Date: Wed, 6 Dec 2023 21:10:48 +0800 Subject: feat: move test to src and add submodule googletest --- src/core/function/basic/GpgFunctionObject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/function/basic/GpgFunctionObject.h') diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index 619cad04..dd06608d 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -64,7 +64,7 @@ class SingletonFunctionObject : public ChannelObject { * @param channel * @return T& */ - static auto GetInstance(int channel = GpgFrontend::kGpgfrontendDefaultChannel) + static auto GetInstance(int channel = GpgFrontend::kGpgFrontendDefaultChannel) -> T& { static std::mutex g_channel_mutex_map_lock; static std::map g_channel_mutex_map; -- cgit v1.2.3 From f5cf83e4b3fdf1e9ae82b00f39e45e189809c419 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 15 Dec 2023 17:04:59 +0800 Subject: fix: slove some issues on memory and intilizations --- src/core/function/basic/GpgFunctionObject.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/function/basic/GpgFunctionObject.h') diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index dd06608d..afe81131 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -216,7 +216,8 @@ class SingletonFunctionObject : public ChannelObject { * * @param channel */ - explicit SingletonFunctionObject(int channel) : ChannelObject(channel) {} + explicit SingletonFunctionObject(int channel) + : ChannelObject(channel, typeid(T).name()) {} /** * @brief Destroy the Singleton Function Object object -- cgit v1.2.3 From f9a49043c35e73fc2d4ffb3ed9b39c33849c43b3 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 15 Dec 2023 21:14:17 +0800 Subject: fix: slove threading and memory issues --- src/core/function/basic/GpgFunctionObject.h | 86 +++++++++-------------------- 1 file changed, 26 insertions(+), 60 deletions(-) (limited to 'src/core/function/basic/GpgFunctionObject.h') 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 +#include + +#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 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 g_channel_mutex_map; - - SPDLOG_TRACE("try to get instance of type: {} at channel: {}", - typeid(T).name(), channel); - - { - std::lock_guard 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, T>, "T not derived from SingletonFunctionObject"); - auto* p_storage = - SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( - typeid(T)); - SPDLOG_TRACE("get singleton storage result, p_storage: {}", - static_cast(p_storage)); - - auto* p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); - SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, - static_cast(p_pbj)); - - if (p_pbj == nullptr) { - SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, - typeid(T).name()); - - // lock this channel - std::lock_guard guard(g_channel_mutex_map[channel]); - - // double check - if (p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); - p_pbj != nullptr) { - return *p_pbj; - } - - // do create object of this channel - auto new_obj = - ConvertToChannelObjectPtr<>(SecureCreateUniqueObject(channel)); - return *static_cast( - p_storage->SetObjectInChannel(channel, std::move(new_obj))); + const auto& type = typeid(T); + std::lock_guard guard(GetGlobalFunctionObjectTypeLock(type)); + auto* channel_object = GetChannelObjectInstance(type, channel); + if (channel_object == nullptr) { + channel_object = CreateChannelObjectInstance( + type, channel, + ConvertToChannelObjectPtr(SecureCreateUniqueObject(channel))); } - return *p_pbj; + return *static_cast(channel_object); } /** @@ -126,23 +105,10 @@ class SingletonFunctionObject : public ChannelObject { static_assert(std::is_base_of_v, T>, "T not derived from SingletonFunctionObject"); - auto* p_storage = - SingletonStorageCollection::GetInstance(false)->GetSingletonStorage( - typeid(T)); - SPDLOG_TRACE("get singleton storage result, p_storage: {}", - static_cast(p_storage)); - - auto p_pbj = static_cast(p_storage->FindObjectInChannel(channel)); - SPDLOG_TRACE("find channel object result, channel {}, p_pbj: {}", channel, - static_cast(p_pbj)); - - if (p_pbj == nullptr) { - SPDLOG_TRACE("create channel object, channel {}, type: {}", channel, - typeid(T).name()); - return *static_cast( - p_storage->SetObjectInChannel(channel, factory())); - } - return *p_pbj; + const auto& type = typeid(T); + std::lock_guard guard(GetGlobalFunctionObjectTypeLock(type)); + return *static_cast( + CreateChannelObjectInstance(type, channel, factory())); } /** -- cgit v1.2.3