Use shared_ptr to store plugins (#1640)

This commit is contained in:
An Tao 2023-06-14 10:13:12 +08:00 committed by GitHub
parent 44b6916d7e
commit 586fd6d67a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 105 additions and 22 deletions

View File

@ -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,

View File

@ -33,6 +33,7 @@ namespace drogon
{
class DrObjectBase;
using DrAllocFunc = std::function<DrObjectBase *()>;
using DrSharedAllocFunc = std::function<std::shared_ptr<DrObjectBase>()>;
/**
* @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<DrObjectBase> 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<std::string, DrAllocFunc> &getMap();
static std::unordered_map<std::string,
std::pair<DrAllocFunc, DrSharedAllocFunc>>
&getMap();
};
} // namespace drogon

View File

@ -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<DrObjectBase> {
return std::make_shared<T>();
});
}
template <typename D>
typename std::enable_if<!std::is_default_constructible<D>::value,

View File

@ -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 <typename T>
std::shared_ptr<T> getSharedPlugin()
{
static_assert(IsPlugin<T>::value,
"The Template parameter must be a subclass of "
"PluginBase");
assert(isRunning());
static auto pluginPtr =
std::dynamic_pointer_cast<T>(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<PluginBase> getSharedPlugin(
const std::string &name) = 0;
/* The following is a series of methods of AOP */
/// Register a beginning advice

View File

@ -39,7 +39,9 @@ class DROGON_EXPORT GlobalFilters
public std::enable_shared_from_this<GlobalFilters>
{
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
} // namespace drogon

View File

@ -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<DrObjectBase> 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<DrObjectBase>(iter->second.first());
}
else
return nullptr;
}
const std::shared_ptr<DrObjectBase> &DrClassMap::getSingleInstance(
const std::string &className)
{
@ -68,7 +84,7 @@ const std::shared_ptr<DrObjectBase> &DrClassMap::getSingleInstance(
if (iter != singleInstanceMap.end())
return iter->second;
}
auto newObj = std::shared_ptr<DrObjectBase>(newObject(className));
auto newObj = newSharedObject(className);
{
std::lock_guard<std::mutex> lock(mtx);
auto ret = singleInstanceMap.insert(
@ -95,8 +111,11 @@ std::vector<std::string> DrClassMap::getAllClassName()
return ret;
}
std::unordered_map<std::string, DrAllocFunc> &DrClassMap::getMap()
std::unordered_map<std::string, std::pair<DrAllocFunc, DrSharedAllocFunc>>
&DrClassMap::getMap()
{
static std::unordered_map<std::string, DrAllocFunc> map;
static std::unordered_map<std::string,
std::pair<DrAllocFunc, DrSharedAllocFunc>>
map;
return map;
}

View File

@ -348,6 +348,12 @@ PluginBase *HttpAppFrameworkImpl::getPlugin(const std::string &name)
{
return pluginsManagerPtr_->getPlugin(name);
}
std::shared_ptr<PluginBase> HttpAppFrameworkImpl::getSharedPlugin(
const std::string &name)
{
return pluginsManagerPtr_->getSharedPlugin(name);
}
void HttpAppFrameworkImpl::addPlugin(
const std::string &name,
const std::vector<std::string> &dependencies,

View File

@ -57,6 +57,8 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
}
PluginBase *getPlugin(const std::string &name) override;
std::shared_ptr<PluginBase> getSharedPlugin(
const std::string &name) override;
void addPlugins(const Json::Value &configs);
void addPlugin(const std::string &name,
const std::vector<std::string> &dependencies,

View File

@ -88,16 +88,14 @@ void PluginsManager::initializeAllPlugins(
}
void PluginsManager::createPlugin(const std::string &pluginName)
{
auto *p = DrClassMap::newObject(pluginName);
auto *pluginPtr = dynamic_cast<PluginBase *>(p);
auto pluginPtr = std::dynamic_pointer_cast<PluginBase>(
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<PluginBase> PluginsManager::getSharedPlugin(
const std::string &pluginName)
{
auto iter = pluginsMap_.find(pluginName);
if (iter != pluginsMap_.end())
{
return iter->second;
}
return nullptr;
}

View File

@ -18,7 +18,7 @@
namespace drogon
{
using PluginBasePtr = std::unique_ptr<PluginBase>;
using PluginBasePtr = std::shared_ptr<PluginBase>;
class PluginsManager : trantor::NonCopyable
{
@ -29,6 +29,8 @@ class PluginsManager : trantor::NonCopyable
PluginBase *getPlugin(const std::string &pluginName);
std::shared_ptr<PluginBase> getSharedPlugin(const std::string &pluginName);
~PluginsManager();
private:

@ -1 +1 @@
Subproject commit 60fb0a0577eb06c1725e927c8ef3d549611090c0
Subproject commit 8601bb91130f4254f9cc710d80860f4c210c8b58