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 : #ifndef __PLUMED_core_ActionRegister_h 23 : #define __PLUMED_core_ActionRegister_h 24 : 25 : #include "RegisterBase.h" 26 : 27 : #include "tools/Keywords.h" 28 : 29 : namespace PLMD { 30 : 31 : class Action; 32 : class ActionOptions; 33 : 34 : struct ActionRegisterPointers { 35 : /// Pointer to a function which, given the options, create an Action 36 : typedef std::unique_ptr<Action>(*creator_pointer)(const ActionOptions&); 37 : /// Pointer to a function which, returns the keywords allowed 38 : typedef void(*keywords_pointer)(Keywords&); 39 : creator_pointer create; 40 : keywords_pointer keys; 41 : }; 42 : 43 : /// Register holding all the allowed keywords. 44 : /// This is a register which holds a map between strings (directives) and function pointers. 45 : /// The function pointers are pointing to functions which create an object of 46 : /// the corresponding class given the corresponding options (ActionOptions). 47 : /// There should be only one of there objects allocated. 48 : /// Actions should be registered here at the beginning of execution 49 : /// 50 5316 : class ActionRegister: 51 : public RegisterBase<ActionRegisterPointers> { 52 : 53 : typedef ActionRegisterPointers::creator_pointer creator_pointer; 54 : typedef ActionRegisterPointers::keywords_pointer keywords_pointer; 55 : typedef ActionRegisterPointers Pointers; 56 : 57 : public: 58 : ID add(std::string key,creator_pointer cp,keywords_pointer kp); 59 : /// Create an Action of the type indicated in the options 60 : /// \param ao object containing information for initialization, such as the full input line, a pointer to PlumedMain, etc 61 : std::unique_ptr<Action> create(const ActionOptions&ao); 62 : std::unique_ptr<Action> create(const std::vector<void*> & images,const ActionOptions&ao); 63 : /// Print out the keywords for an action in html/vim ready for input into the manual 64 : bool printManual(const std::string& action, const bool& vimout, const bool& spellout); 65 : /// Retrieve a keywords object for a particular action 66 : bool getKeywords( const std::string& action, Keywords& keys ); 67 : void getKeywords(const std::vector<void*> & images, const std::string& action, Keywords& keys); 68 : /// Print out a template command for an action 69 : bool printTemplate(const std::string& action, bool include_optional); 70 : std::vector<std::string> getActionNames() const; 71 : }; 72 : 73 : /// Function returning a reference to the ActionRegister. 74 : /// \relates ActionRegister 75 : /// To avoid problems with order of initialization, this function contains 76 : /// a static ActionRegister which is built the first time the function is called. 77 : /// In this manner, it is always initialized before it's used 78 : ActionRegister& actionRegister(); 79 : 80 : template<typename T> 81 : inline constexpr bool isActionType = std::is_base_of<Action, T>::value; 82 : //in C++20 you we'll make this a concept 83 : //template<typename T> 84 : //concept ActionType = std::is_base_of<::PLMD::Action, T>::value; 85 : //so the template will be template<ActionType ActionType>class ActionRegistration{...} 86 : //without the explicit need of the static assert 87 : 88 : ///Each instance of this specialized class represents an action that can be called 89 : ///with the specified directive. 90 : ///As soon it goes out of scope it will deregister the directive from the singleton ActionRegister 91 : template<typename ActionClass> 92 : class ActionRegistration { 93 : ActionRegister::ID id; 94 51163 : static std::unique_ptr<Action> create(const ActionOptions&ao) { 95 101140 : return std::make_unique<ActionClass>(ao); 96 : } 97 : public: 98 : ///On construction register the ActionClass with the wanted directive 99 2328408 : ActionRegistration(std::string_view directive): 100 2328408 : id(actionRegister().add(directive.data(),create,ActionClass::registerKeywords)) 101 : { 102 : static_assert(isActionType<ActionClass>, 103 : "ActionRegistration accepts only class that inherit from Action"); 104 2328408 : } 105 : ///On destruction deregister the ActionClass (useful when you unload a shared object) 106 2328408 : ~ActionRegistration() {actionRegister().remove(id);} 107 : }; 108 : } //PLMD 109 : 110 : #define PLUMED_CONCATENATE_DIRECT(s1, s2) s1##s2 111 : #define PLUMED_CONCATENATE(s1, s2) PLUMED_CONCATENATE_DIRECT(s1, s2) 112 : 113 : /// Shortcut for Action registration 114 : /// \relates PLMD::ActionRegister 115 : /// For easier registration, this file also provides a macro PLUMED_REGISTER_ACTION. 116 : /// \param classname the name of the class to be registered 117 : /// \param directive a string containing the corresponding directive 118 : /// This macro should be used in the .cpp file of the corresponding class 119 : #define PLUMED_REGISTER_ACTION(classname,directive) \ 120 : namespace {::PLMD::ActionRegistration<classname> \ 121 : PLUMED_CONCATENATE(classname##Registerer,__LINE__)(directive);} 122 : #endif 123 :