From 9acf5d7adbcdd5d602aea96b51586be17171e9ec Mon Sep 17 00:00:00 2001 From: Giovanni Bussi <giovanni.bussi@gmail.com> Date: Fri, 9 Dec 2011 15:59:01 +0100 Subject: [PATCH] DLLoader class It takes care of dynamic loading, and unload libraries when plumedMain is destroyed. This allows for a complete memory cleanup at the end of execution. --- src/ActionRegister.cpp | 14 +++++++++ src/ActionRegister.h | 3 ++ src/DLLoader.cpp | 49 ++++++++++++++++++++++++++++++ src/DLLoader.h | 21 +++++++++++++ src/PlumedMain.cpp | 67 +++++++++++++++++++----------------------- src/PlumedMain.h | 3 ++ 6 files changed, 120 insertions(+), 37 deletions(-) create mode 100644 src/DLLoader.cpp create mode 100644 src/DLLoader.h diff --git a/src/ActionRegister.cpp b/src/ActionRegister.cpp index 695d46d7f..218064dd4 100644 --- a/src/ActionRegister.cpp +++ b/src/ActionRegister.cpp @@ -9,11 +9,25 @@ using namespace std; using namespace PLMD; +ActionRegister::~ActionRegister(){ + if(m.size()>0) + for(mIterator p=m.begin();p!=m.end();++p) + std::cerr<<"WARNING: directive "<<p->first<<" has not been properly unregistered\n"; +} + ActionRegister& PLMD::actionRegister(){ static ActionRegister ans; return ans; } +void ActionRegister::remove(creator_pointer f){ + for(mIterator p=m.begin();p!=m.end();++p){ + if((*p).second==f){ + m.erase(p); break; + } + } +} + void ActionRegister::add(string key,creator_pointer f){ if(m.count(key)){ m.erase(key); diff --git a/src/ActionRegister.h b/src/ActionRegister.h index b2b83415e..f0b652abf 100644 --- a/src/ActionRegister.h +++ b/src/ActionRegister.h @@ -41,6 +41,8 @@ public: /// Create an Action of the type indicated in the options /// \param ao object containing information for initialization, such as the full input line, a pointer to PlumedMain, etc Action* create(const ActionOptions&ao); + void remove(creator_pointer); + ~ActionRegister(); }; /// Function returning a reference to the ActionRegister. @@ -66,6 +68,7 @@ std::ostream & operator<<(std::ostream &log,const ActionRegister&ar); static PLMD::Action* create(const PLMD::ActionOptions&ao){return new classname(ao);} \ public: \ classname##RegisterMe(){PLMD::actionRegister().add(directive,create);}; \ + ~classname##RegisterMe(){PLMD::actionRegister().remove(create);}; \ } classname##RegisterMeObject; diff --git a/src/DLLoader.cpp b/src/DLLoader.cpp new file mode 100644 index 000000000..05d8db60c --- /dev/null +++ b/src/DLLoader.cpp @@ -0,0 +1,49 @@ +#include "DLLoader.h" +#ifdef __PLUMED_HAS_DLOPEN +#include <dlfcn.h> +#endif + +#include <iostream> + +using namespace PLMD; + +bool DLLoader::installed(){ +#ifdef __PLUMED_HAS_DLOPEN + return true; +#else + return false; +#endif +} + + +void* DLLoader::load(const std::string&s){ +#ifdef __PLUMED_HAS_DLOPEN + void* p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL); + if(!p){ + lastError=dlerror(); + } else { + lastError=""; + handles.push(p); + } + return p; +#else + return NULL; +#endif +} + +const std::string & DLLoader::error(){ + return lastError; +} + +DLLoader::~DLLoader(){ +#ifdef __PLUMED_HAS_DLOPEN + while(!handles.empty()){ + void* p=handles.top(); + handles.pop(); + dlclose(p); + } +#endif +} + + + diff --git a/src/DLLoader.h b/src/DLLoader.h new file mode 100644 index 000000000..bb30d2bea --- /dev/null +++ b/src/DLLoader.h @@ -0,0 +1,21 @@ +#ifndef __PLUMED_DLLoader_h +#define __PLUMED_DLLoader_h + +#include <stack> +#include <string> + +namespace PLMD{ + +class DLLoader{ + std::stack<void*> handles; + std::string lastError; +public: + ~DLLoader(); + void* load(const std::string&); + const std::string & error(); + static bool installed(); +}; + +} + +#endif diff --git a/src/PlumedMain.cpp b/src/PlumedMain.cpp index 19c71b802..134071a70 100644 --- a/src/PlumedMain.cpp +++ b/src/PlumedMain.cpp @@ -1,7 +1,3 @@ -#ifdef __PLUMED_HAS_DLOPEN -#include <dlfcn.h> -#endif - #include "PlumedMain.h" #include "Tools.h" #include <cstring> @@ -429,39 +425,36 @@ void PlumedMain::justApply(){ } void PlumedMain::load(std::vector<std::string> & words){ -#ifdef __PLUMED_HAS_DLOPEN - string s=words[1]; - assert(words.size()==2); - size_t n=s.find_last_of("."); - string extension=""; - string base=s; - if(n!=std::string::npos && n<s.length()-1) extension=s.substr(n+1); - if(n!=std::string::npos && n<s.length()) base=s.substr(0,n); - if(extension=="cpp"){ - string cmd="plumed mklib "+s; - log<<"Executing: "<<cmd; - if(comm.Get_size()>0) log<<" (only on master node)"; - log<<"\n"; - if(comm.Get_rank()==0) system(cmd.c_str()); - comm.Barrier(); - base="./"+base; - } - s=base+"."+soext; - void *p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL); - if(!p){ - log<<"ERROR\n"; - log<<"I cannot load library "<<words[1].c_str()<<"\n"; - log<<dlerror(); - log<<"\n"; - this->exit(1); - } - log<<"Loading shared library "<<s.c_str()<<"\n"; - log<<"Here is the new list of available actions\n"; - log<<actionRegister(); -#else - (void) words; - assert(0); // Loading not enabled; please recompile with -D__PLUMED_HAS_DLOPEN -#endif + if(DLLoader::installed()){ + string s=words[1]; + assert(words.size()==2); + size_t n=s.find_last_of("."); + string extension=""; + string base=s; + if(n!=std::string::npos && n<s.length()-1) extension=s.substr(n+1); + if(n!=std::string::npos && n<s.length()) base=s.substr(0,n); + if(extension=="cpp"){ + string cmd="plumed mklib "+s; + log<<"Executing: "<<cmd; + if(comm.Get_size()>0) log<<" (only on master node)"; + log<<"\n"; + if(comm.Get_rank()==0) system(cmd.c_str()); + comm.Barrier(); + base="./"+base; + } + s=base+"."+soext; + void *p=dlloader.load(s); + if(!p){ + log<<"ERROR\n"; + log<<"I cannot load library "<<words[1].c_str()<<"\n"; + log<<dlloader.error(); + log<<"\n"; + this->exit(1); + } + log<<"Loading shared library "<<s.c_str()<<"\n"; + log<<"Here is the new list of available actions\n"; + log<<actionRegister(); + } else assert(0); // Loading not enabled; please recompile with -D__PLUMED_HAS_DLOPEN } double PlumedMain::getBias() const{ diff --git a/src/PlumedMain.h b/src/PlumedMain.h index f4e0ca823..d1ddee4df 100644 --- a/src/PlumedMain.h +++ b/src/PlumedMain.h @@ -8,6 +8,7 @@ #include <cstdio> #include <string> #include <vector> +#include "DLLoader.h" // !!!!!!!!!!!!!!!!!!!!!! DANGER !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 @@ -48,6 +49,8 @@ public: PlumedCommunicator comm; private: + DLLoader dlloader; + WithCmd* grex; /// Flag to avoid double initialization bool initialized; -- GitLab