Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-2023 The plumed team 3 : (see the PEOPLE file at the root of the distribution for a list of names) 4 : 5 : See http://www.plumed.org for more information. 6 : 7 : This file is part of plumed, version 2. 8 : 9 : plumed is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU Lesser General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : plumed is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU Lesser General Public License for more details. 18 : 19 : You should have received a copy of the GNU Lesser General Public License 20 : along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #include "RegisterBase.h" 23 : 24 : #include <mutex> 25 : #include "tools/Tools.h" 26 : 27 : namespace PLMD { 28 : 29 : namespace { 30 5316 : class Singleton { 31 : public: 32 : /// Mutex to avoid simultaneous registrations from multiple threads 33 : std::mutex registeringMutex; 34 : 35 : /// Count simultaneous registrations 36 : /// This is here if in the future we want to expand to recursive registrations 37 : unsigned registeringCounter=0; 38 : 39 : /// Take care of all exisiting registers 40 : std::vector<Register*> registers; 41 : 42 : /// Full path of the registering library 43 : std::string fullPath; 44 : }; 45 : 46 4880283 : Singleton & getSingleton() { 47 4880283 : static Singleton singleton; 48 4880283 : return singleton; 49 : } 50 : 51 : } 52 : 53 51 : Register::RegistrationLock::RegistrationLock(const std::string & fullPath): 54 51 : active(true) 55 : { 56 51 : pushDLRegistration(fullPath); 57 51 : } 58 : 59 51 : Register::RegistrationLock::~RegistrationLock() noexcept { 60 51 : if(active) popDLRegistration(); 61 51 : } 62 : 63 0 : Register::RegistrationLock::RegistrationLock(RegistrationLock&& other) noexcept: 64 0 : active(other.active) 65 : { 66 0 : other.active=false; 67 0 : } 68 : 69 51 : Register::RegistrationLock Register::registrationLock(const std::string & fullPath) { 70 51 : return RegistrationLock(fullPath); 71 : } 72 : 73 51 : void Register::pushDLRegistration(const std::string & fullPath) { 74 51 : auto & singleton=getSingleton(); 75 51 : singleton.registeringMutex.lock(); 76 51 : singleton.fullPath=fullPath; 77 51 : if(singleton.registeringCounter>0) { 78 : singleton.registeringMutex.unlock(); 79 0 : plumed_error()<<"recursive registrations are technically possible but disabled at this stage "<<singleton.registeringCounter; 80 : } 81 51 : singleton.registeringCounter++; 82 51 : } 83 : 84 51 : void Register::popDLRegistration() noexcept { 85 51 : auto & singleton=getSingleton(); 86 153 : for(auto & reg : singleton.registers) reg->clearStaged(); 87 51 : singleton.registeringCounter--; 88 : singleton.registeringMutex.unlock(); 89 51 : } 90 : 91 51 : void Register::completeAllRegistrations(void* image) { 92 51 : auto & singleton=getSingleton(); 93 153 : for(auto & reg : singleton.registers) reg->completeRegistration(image); 94 51 : } 95 : 96 244 : std::string Register::imageToString(void* image) { 97 244 : std::stringstream ss; 98 : ss << image; 99 244 : return ss.str(); 100 244 : } 101 : 102 2429433 : bool Register::isDLRegistering() noexcept { 103 2429433 : auto & singleton=getSingleton(); 104 2429433 : return singleton.registeringCounter>0; 105 : } 106 : 107 2429433 : const std::string Register::getRegisteringFullPath() noexcept { 108 2429433 : auto & singleton=getSingleton(); 109 2429433 : return singleton.fullPath; 110 : } 111 : 112 10632 : Register::Register() { 113 10632 : auto & singleton=getSingleton(); 114 : // this is to protect insertion 115 10632 : std::unique_lock lock(singleton.registeringMutex); 116 10632 : singleton.registers.push_back(this); 117 10632 : } 118 : 119 10632 : Register::~Register() noexcept { 120 10632 : auto & singleton=getSingleton(); 121 : // this is to protect removal 122 10632 : std::unique_lock lock(singleton.registeringMutex); 123 10632 : auto it=std::find(singleton.registers.begin(),singleton.registers.end(),this); 124 10632 : if(it!=singleton.registers.end()) singleton.registers.erase(it); 125 10632 : } 126 : 127 41 : std::vector<std::string> Register::getKeysWithDLHandle(void* image) const { 128 : std::vector<std::string> res; 129 41 : const auto prefix=imageToString(image)+":"; 130 18073 : for(auto & k : getKeys()) { 131 18032 : if(Tools::startWith(k,prefix)) { 132 82 : if(!std::getenv("PLUMED_LOAD_ACTION_DEBUG")) k=k.substr(prefix.length()); 133 41 : res.push_back(k); 134 : } 135 41 : } 136 41 : return res; 137 0 : } 138 : 139 878 : std::ostream & operator<<(std::ostream &log,const Register ®) { 140 878 : std::vector<std::string> s(reg.getKeys()); 141 201501 : for(unsigned i=0; i<s.size(); i++) log<<" "<<s[i]<<"\n"; 142 878 : return log; 143 878 : } 144 : 145 : 146 : }