From 308df2151192f297516d5f8cf0fdacd4adcf4d7a Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 6 Aug 2014 15:32:41 +0200 Subject: [PATCH] Modules: Add a module version of CJob Signed-off-by: Uli Schlachter --- include/znc/Modules.h | 37 ++++++++++++++++++++++++++++++++ include/znc/Threads.h | 2 ++ src/Modules.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/include/znc/Modules.h b/include/znc/Modules.h index 02433e8b..df864864 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -177,6 +178,29 @@ private: FPTimer_t m_pFBCallback; }; +#ifdef HAVE_PTHREAD +/// A CJob version which can be safely used in modules. The job will be +/// cancelled when the module is unloaded. +class CModuleJob : public CJob { +public: + CModuleJob(CModule *pModule, const CString& sName, const CString& sDesc) + : CJob(), m_pModule(pModule), m_sName(sName), m_sDescription(sDesc) { + } + virtual ~CModuleJob(); + + // Getters + CModule* GetModule() const { return m_pModule; } + const CString& GetName() const { return m_sName; } + const CString& GetDescription() const { return m_sDescription; } + // !Getters + +protected: + CModule* m_pModule; + const CString m_sName; + const CString m_sDescription; +}; +#endif + class CModInfo { public: typedef CModule* (*ModLoader)(ModHandle p, CUser* pUser, CIRCNetwork* pNetwork, const CString& sModName, const CString& sModPath); @@ -885,6 +909,16 @@ public: virtual void ListSockets(); // !Socket stuff +#ifdef HAVE_PTHREAD + // Job stuff + void AddJob(CModuleJob *pJob); + void CancelJob(CModuleJob *pJob); + bool CancelJob(const CString& sJobName); + void CancelJobs(const std::set& sJobs); + bool UnlinkJob(CModuleJob *pJob); + // !Job stuff +#endif + // Command stuff /// Register the "Help" command. void AddHelpCommand(); @@ -1052,6 +1086,9 @@ protected: CString m_sDescription; std::set m_sTimers; std::set m_sSockets; +#ifdef HAVE_PTHREAD + std::set m_sJobs; +#endif ModHandle m_pDLL; CSockManager* m_pManager; CUser* m_pUser; diff --git a/include/znc/Threads.h b/include/znc/Threads.h index 5c614994..a83fdc46 100644 --- a/include/znc/Threads.h +++ b/include/znc/Threads.h @@ -213,6 +213,8 @@ private: * After you create a new instance of your class, you can pass it to * CThreadPool()::Get().addJob(job) to start it. The thread pool automatically * deletes your class after it finished. + * + * For modules you should use CModuleJob instead. */ class CJob { public: diff --git a/src/Modules.cpp b/src/Modules.cpp index 5e8e39a7..b696831f 100644 --- a/src/Modules.cpp +++ b/src/Modules.cpp @@ -157,6 +157,10 @@ CModule::~CModule() { } SaveRegistry(); + +#ifdef HAVE_PTHREAD + CancelJobs(m_sJobs); +#endif } void CModule::SetUser(CUser* pUser) { m_pUser = pUser; } @@ -449,6 +453,52 @@ void CModule::ListSockets() { PutModule(Table); } +#ifdef HAVE_PTHREAD +CModuleJob::~CModuleJob() +{ + m_pModule->UnlinkJob(this); +} + +void CModule::AddJob(CModuleJob *pJob) +{ + CThreadPool::Get().addJob(pJob); + m_sJobs.insert(pJob); +} + +void CModule::CancelJob(CModuleJob *pJob) +{ + if (pJob == NULL) + return; + // Destructor calls UnlinkJob and removes the job from m_sJobs + CThreadPool::Get().cancelJob(pJob); +} + +bool CModule::CancelJob(const CString& sJobName) +{ + set::iterator it; + for (it = m_sJobs.begin(); it != m_sJobs.end(); ++it) { + if ((*it)->GetName().Equals(sJobName)) { + CancelJob(*it); + return true; + } + } + return false; +} + +void CModule::CancelJobs(const std::set& sJobs) +{ + set sPlainJobs(sJobs.begin(), sJobs.end()); + + // Destructor calls UnlinkJob and removes the jobs from m_sJobs + CThreadPool::Get().cancelJobs(sPlainJobs); +} + +bool CModule::UnlinkJob(CModuleJob *pJob) +{ + return 0 != m_sJobs.erase(pJob); +} +#endif + bool CModule::AddCommand(const CModCommand& Command) { if (Command.GetFunction() == NULL)