From 586fd6d67af597b009c9fbd10131f11e40d6c54a Mon Sep 17 00:00:00 2001 From: An Tao Date: Wed, 14 Jun 2023 10:13:12 +0800 Subject: [PATCH] Use shared_ptr to store plugins (#1640) --- examples/client_example/main.cc | 2 +- lib/inc/drogon/DrClassMap.h | 15 +++++++++--- lib/inc/drogon/DrObject.h | 8 +++++-- lib/inc/drogon/HttpAppFramework.h | 32 +++++++++++++++++++++++++- lib/inc/drogon/plugins/GlobalFilters.h | 6 +++-- lib/src/DrClassMap.cc | 31 ++++++++++++++++++++----- lib/src/HttpAppFrameworkImpl.cc | 6 +++++ lib/src/HttpAppFrameworkImpl.h | 2 ++ lib/src/PluginsManager.cc | 19 +++++++++++---- lib/src/PluginsManager.h | 4 +++- trantor | 2 +- 11 files changed, 105 insertions(+), 22 deletions(-) diff --git a/examples/client_example/main.cc b/examples/client_example/main.cc index 805a9e62..d991c5a3 100644 --- a/examples/client_example/main.cc +++ b/examples/client_example/main.cc @@ -18,7 +18,7 @@ int main() { auto client = HttpClient::newHttpClient("http://www.baidu.com"); client->setSockOptCallback([](int fd) { - std::cout << "setSockOptCallback" << std::endl; + std::cout << "setSockOptCallback:" << fd << std::endl; #ifdef __linux__ int optval = 10; ::setsockopt(fd, diff --git a/lib/inc/drogon/DrClassMap.h b/lib/inc/drogon/DrClassMap.h index 201aa144..6c5c7d08 100644 --- a/lib/inc/drogon/DrClassMap.h +++ b/lib/inc/drogon/DrClassMap.h @@ -33,6 +33,7 @@ namespace drogon { class DrObjectBase; using DrAllocFunc = std::function; +using DrSharedAllocFunc = std::function()>; /** * @brief A map class which can create DrObjects from names. @@ -47,7 +48,8 @@ class DROGON_EXPORT DrClassMap * @param func The function which can create a new instance of the class. */ static void registerClass(const std::string &className, - const DrAllocFunc &func); + const DrAllocFunc &func, + const DrSharedAllocFunc &sharedFunc = nullptr); /** * @brief Create a new instance of the class named by className @@ -57,6 +59,12 @@ class DROGON_EXPORT DrClassMap */ static DrObjectBase *newObject(const std::string &className); + /** + * @brief Get the shared_ptr instance of the class named by className + */ + static std::shared_ptr newSharedObject( + const std::string &className); + /** * @brief Get the singleton object of the class named by className * @@ -129,7 +137,8 @@ class DROGON_EXPORT DrClassMap } protected: - static std::unordered_map &getMap(); + static std::unordered_map> + &getMap(); }; - } // namespace drogon diff --git a/lib/inc/drogon/DrObject.h b/lib/inc/drogon/DrObject.h index 40955c16..72b25f1a 100644 --- a/lib/inc/drogon/DrObject.h +++ b/lib/inc/drogon/DrObject.h @@ -102,8 +102,12 @@ class DrObject : public virtual DrObjectBase void>::type registerClass() { - DrClassMap::registerClass(className(), - []() -> DrObjectBase * { return new T; }); + DrClassMap::registerClass( + className(), + []() -> DrObjectBase * { return new T; }, + []() -> std::shared_ptr { + return std::make_shared(); + }); } template typename std::enable_if::value, diff --git a/lib/inc/drogon/HttpAppFramework.h b/lib/inc/drogon/HttpAppFramework.h index 782c229e..5be17c48 100644 --- a/lib/inc/drogon/HttpAppFramework.h +++ b/lib/inc/drogon/HttpAppFramework.h @@ -199,7 +199,26 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable return pluginPtr; } - /// Get the plugin object registered in the framework + /// Get the shared_ptr plugin object registered in the framework + /** + * @note + * This method is usually called after the framework runs. + * Calling this method in the initAndStart() method of plugins is also + * valid. + */ + template + std::shared_ptr getSharedPlugin() + { + static_assert(IsPlugin::value, + "The Template parameter must be a subclass of " + "PluginBase"); + assert(isRunning()); + static auto pluginPtr = + std::dynamic_pointer_cast(getSharedPlugin(T::classTypeName())); + return pluginPtr; + } + + /// @brief the plugin object registered in the framework /** * @param name is the class name of the plugin. * @@ -210,6 +229,17 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable */ virtual PluginBase *getPlugin(const std::string &name) = 0; + /** + * @brief Get the shared_ptr plugin object registered in the framework + * + * @note + * This method is usually called after the framework runs. + * Calling this method in the initAndStart() method of plugins is also + * valid. + */ + virtual std::shared_ptr getSharedPlugin( + const std::string &name) = 0; + /* The following is a series of methods of AOP */ /// Register a beginning advice diff --git a/lib/inc/drogon/plugins/GlobalFilters.h b/lib/inc/drogon/plugins/GlobalFilters.h index 5d882309..a94da2c2 100644 --- a/lib/inc/drogon/plugins/GlobalFilters.h +++ b/lib/inc/drogon/plugins/GlobalFilters.h @@ -39,7 +39,9 @@ class DROGON_EXPORT GlobalFilters public std::enable_shared_from_this { public: - GlobalFilters() = default; + GlobalFilters() + { + } void initAndStart(const Json::Value &config) override; void shutdown() override; @@ -49,4 +51,4 @@ class DROGON_EXPORT GlobalFilters bool regexFlag_{false}; }; } // namespace plugin -} // namespace drogon \ No newline at end of file +} // namespace drogon diff --git a/lib/src/DrClassMap.cc b/lib/src/DrClassMap.cc index ef23d8ab..2f4c07f7 100644 --- a/lib/src/DrClassMap.cc +++ b/lib/src/DrClassMap.cc @@ -40,10 +40,12 @@ static std::mutex &getMapMutex() } // namespace drogon void DrClassMap::registerClass(const std::string &className, - const DrAllocFunc &func) + const DrAllocFunc &func, + const DrSharedAllocFunc &sharedFunc) { LOG_TRACE << "Register class:" << className; - getMap().insert(std::make_pair(className, func)); + getMap().insert( + std::make_pair(className, std::make_pair(func, sharedFunc))); } DrObjectBase *DrClassMap::newObject(const std::string &className) @@ -51,12 +53,26 @@ DrObjectBase *DrClassMap::newObject(const std::string &className) auto iter = getMap().find(className); if (iter != getMap().end()) { - return iter->second(); + return iter->second.first(); } else return nullptr; } +std::shared_ptr DrClassMap::newSharedObject( + const std::string &className) +{ + auto iter = getMap().find(className); + if (iter != getMap().end()) + { + if (iter->second.second) + return iter->second.second(); + else + return std::shared_ptr(iter->second.first()); + } + else + return nullptr; +} const std::shared_ptr &DrClassMap::getSingleInstance( const std::string &className) { @@ -68,7 +84,7 @@ const std::shared_ptr &DrClassMap::getSingleInstance( if (iter != singleInstanceMap.end()) return iter->second; } - auto newObj = std::shared_ptr(newObject(className)); + auto newObj = newSharedObject(className); { std::lock_guard lock(mtx); auto ret = singleInstanceMap.insert( @@ -95,8 +111,11 @@ std::vector DrClassMap::getAllClassName() return ret; } -std::unordered_map &DrClassMap::getMap() +std::unordered_map> + &DrClassMap::getMap() { - static std::unordered_map map; + static std::unordered_map> + map; return map; } diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index fb2114eb..2fe8c3b2 100644 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -348,6 +348,12 @@ PluginBase *HttpAppFrameworkImpl::getPlugin(const std::string &name) { return pluginsManagerPtr_->getPlugin(name); } + +std::shared_ptr HttpAppFrameworkImpl::getSharedPlugin( + const std::string &name) +{ + return pluginsManagerPtr_->getSharedPlugin(name); +} void HttpAppFrameworkImpl::addPlugin( const std::string &name, const std::vector &dependencies, diff --git a/lib/src/HttpAppFrameworkImpl.h b/lib/src/HttpAppFrameworkImpl.h index 8abf2dfe..8d62cc19 100644 --- a/lib/src/HttpAppFrameworkImpl.h +++ b/lib/src/HttpAppFrameworkImpl.h @@ -57,6 +57,8 @@ class HttpAppFrameworkImpl final : public HttpAppFramework } PluginBase *getPlugin(const std::string &name) override; + std::shared_ptr getSharedPlugin( + const std::string &name) override; void addPlugins(const Json::Value &configs); void addPlugin(const std::string &name, const std::vector &dependencies, diff --git a/lib/src/PluginsManager.cc b/lib/src/PluginsManager.cc index b5d5aa1f..ac9650ec 100644 --- a/lib/src/PluginsManager.cc +++ b/lib/src/PluginsManager.cc @@ -88,16 +88,14 @@ void PluginsManager::initializeAllPlugins( } void PluginsManager::createPlugin(const std::string &pluginName) { - auto *p = DrClassMap::newObject(pluginName); - auto *pluginPtr = dynamic_cast(p); + auto pluginPtr = std::dynamic_pointer_cast( + DrClassMap::newSharedObject(pluginName)); if (!pluginPtr) { - if (p) - delete p; LOG_ERROR << "Plugin " << pluginName << " undefined!"; return; } - pluginsMap_[pluginName].reset(pluginPtr); + pluginsMap_[pluginName] = pluginPtr; } PluginBase *PluginsManager::getPlugin(const std::string &pluginName) { @@ -107,4 +105,15 @@ PluginBase *PluginsManager::getPlugin(const std::string &pluginName) return iter->second.get(); } return nullptr; +} + +std::shared_ptr PluginsManager::getSharedPlugin( + const std::string &pluginName) +{ + auto iter = pluginsMap_.find(pluginName); + if (iter != pluginsMap_.end()) + { + return iter->second; + } + return nullptr; } \ No newline at end of file diff --git a/lib/src/PluginsManager.h b/lib/src/PluginsManager.h index 5f8d03ff..c0abb08f 100644 --- a/lib/src/PluginsManager.h +++ b/lib/src/PluginsManager.h @@ -18,7 +18,7 @@ namespace drogon { -using PluginBasePtr = std::unique_ptr; +using PluginBasePtr = std::shared_ptr; class PluginsManager : trantor::NonCopyable { @@ -29,6 +29,8 @@ class PluginsManager : trantor::NonCopyable PluginBase *getPlugin(const std::string &pluginName); + std::shared_ptr getSharedPlugin(const std::string &pluginName); + ~PluginsManager(); private: diff --git a/trantor b/trantor index 60fb0a05..8601bb91 160000 --- a/trantor +++ b/trantor @@ -1 +1 @@ -Subproject commit 60fb0a0577eb06c1725e927c8ef3d549611090c0 +Subproject commit 8601bb91130f4254f9cc710d80860f4c210c8b58