|
Sierra Toolkit
Version of the Day
|
00001 #ifndef STK_UTIL_DIAG_UserPlugin_h 00002 #define STK_UTIL_DIAG_UserPlugin_h 00003 00004 #include <memory> 00005 #include <map> 00006 #include <vector> 00007 #include <string> 00008 #include <typeinfo> 00009 00010 #include <stk_util/diag/StringUtil.hpp> 00011 #include <stk_util/util/Fortran.hpp> 00012 #include <stk_util/diag/Writer_fwd.hpp> 00013 00038 namespace sierra { 00039 namespace Plugin { 00040 00041 std::string derived_id_name(int derived_id); 00042 00055 class Registry 00056 { 00057 public: 00058 00063 typedef std::pair<const std::type_info *, std::string> NamePair; 00064 00065 // /** 00066 // * @brief Class <b>hash_nocase</b> implements a hash, case insensitive NamePair 00067 // * hash functor. 00068 // * 00069 // */ 00070 // struct hash_nocase 00071 // { 00072 // size_t operator()(const NamePair &n) const { 00073 // return sierra::hash_string_nocase(n.second.c_str()); 00074 // } 00075 // }; 00076 00077 // /** 00078 // * @brief Class <b>hash_nocase</b> implements a hash, case insensitive compare 00079 // * equal NamePair functor. 00080 // * 00081 // */ 00082 // struct equal_nocase : public std::binary_function<NamePair, NamePair, bool> 00083 // { 00084 // bool operator()(const NamePair &lhs, const NamePair &rhs) const { 00085 // sierra::equal_nocase<NamePair::second_type> second_equal_nocase; 00086 00087 // return *lhs.first == *rhs.first && second_equal_nocase(lhs.second, rhs.second); 00088 // } 00089 // }; 00090 00096 struct less_nocase : public std::binary_function<NamePair, NamePair, bool> 00097 { 00098 bool operator()(const NamePair &lhs, const NamePair &rhs) const { 00099 sierra::less_nocase<NamePair::second_type> second_less_nocase; 00100 00101 #ifdef SIERRA_TYPE_INFO_BEFORE_EQUALITY_BUG 00102 return (lhs.first->before(*rhs.first) && *lhs.first != *rhs.first) 00103 || (*lhs.first == *rhs.first && second_less_nocase(lhs.second, rhs.second)); 00104 #else 00105 return lhs.first->before(*rhs.first) 00106 || (*lhs.first == *rhs.first && second_less_nocase(lhs.second, rhs.second)); 00107 #endif 00108 } 00109 }; 00110 00115 typedef std::map<NamePair, void *, less_nocase> RegistryMap; 00116 00117 static RegistryMap &getRegistryMap(); 00118 00123 Registry() 00124 {} 00125 00133 explicit Registry(const NamePair &name_pair) { 00134 registerIt(name_pair, this); 00135 } 00136 00142 virtual ~Registry() 00143 {} 00144 00151 static Registry &rootInstance(); 00152 00175 static void registerDL(const char *so_path, const char *function_name = 0); 00176 00177 template <typename T> 00178 static T getsym(const char *sym); 00179 00198 void registerIt(const NamePair &name_pair, void *func_ptr); 00199 00214 void *getPluginPtr(const NamePair &name_pair) const; 00215 00230 void *getFunctionPtr(const NamePair &name_pair) const; 00231 00242 Registry *getFactoryPtr(const NamePair &name) const; 00243 00254 void *getFuncPtr(const NamePair &name_pair) const; 00255 00266 std::vector<std::string> getDerivedNames(const std::type_info &type) const; 00267 00282 template<class T> 00283 static T &create(const std::string &derived_name) { 00284 return static_cast<T &>(*Registry::rootInstance().getFactoryPtr(std::make_pair(&typeid(T), derived_name))); 00285 } 00286 00295 std::ostream &verbose_print(std::ostream &os) const; 00296 00305 stk_classic::diag::Writer &verbose_print(stk_classic::diag::Writer &dout) const; 00306 }; 00307 00308 inline stk_classic::diag::Writer &operator<<(stk_classic::diag::Writer &dout, const Registry ®istry) { 00309 return registry.verbose_print(dout); 00310 } 00311 00312 00330 template <class Creator, typename S = Creator *(*)()> 00331 class UserPlugin 00332 { 00333 public: 00334 typedef S Signature; 00335 00336 private: 00337 UserPlugin(); 00338 UserPlugin(const UserPlugin&); 00339 UserPlugin &operator=(const UserPlugin&); 00340 00341 public: 00349 static UserPlugin &instance() { 00350 return (UserPlugin<Creator, Signature> &) (Registry::rootInstance()); 00351 } 00352 00368 static void registerCreator(const std::string &derived_name, Signature function) { 00369 Registry::rootInstance().registerIt(std::make_pair(&typeid(Signature), derived_name), (void *) function); 00370 } 00371 00386 static Signature create(const std::string &derived_name) { 00387 Signature creator_function = (Signature) Registry::rootInstance().getPluginPtr(std::make_pair(&typeid(Signature), derived_name)); 00388 00389 return (*creator_function); 00390 } 00391 00406 static Signature create(int derived_id) { 00407 return create(derived_id_name(derived_id)); 00408 } 00409 00419 static bool exists(const std::string &derived_name) { 00420 return Registry::rootInstance().getFuncPtr(std::make_pair(&typeid(Signature), derived_name)) != NULL; 00421 } 00422 00423 static std::vector<std::string> getDerivedNames() { 00424 return Registry::rootInstance().getDerivedNames(typeid(Signature)); 00425 } 00426 00435 template <class DerivedClass> 00436 class Register 00437 { 00438 public: 00439 typedef DerivedClass XDerivedClass; 00440 00450 explicit Register(const std::string &derived_name) 00451 : m_function(DerivedClass::createInstance) 00452 { 00453 UserPlugin<Creator, Signature>::instance().registerCreator(derived_name, m_function); 00454 } 00455 00465 Register(const std::string &derived_name, Signature create_instance) 00466 : m_function(create_instance) 00467 { 00468 UserPlugin<Creator, Signature>::instance().registerCreator(derived_name, m_function); 00469 } 00470 00479 explicit Register(int derived_id) 00480 : m_function(XDerivedClass::createInstance) 00481 { 00482 UserPlugin<Creator, Signature>::instance().registerCreator(derived_id_name(derived_id), m_function); 00483 } 00484 00493 Register(int derived_id, Signature create_instance) 00494 : m_function(create_instance) 00495 { 00496 UserPlugin<Creator, Signature>::instance().registerCreator(derived_id_name(derived_id), m_function); 00497 } 00498 00499 private: 00500 Signature m_function; 00501 }; 00502 }; 00503 00504 00519 template <class S> 00520 class UserSubroutine 00521 { 00522 private: 00523 UserSubroutine(); 00524 UserSubroutine(const UserSubroutine&); 00525 UserSubroutine &operator=(const UserSubroutine&); 00526 00527 public: 00528 typedef S Signature; 00529 00537 inline static UserSubroutine &instance() { 00538 return (UserSubroutine<Signature> &) (Registry::rootInstance()); 00539 } 00540 00556 inline static void registerFunction(const std::string &function_name, Signature *function) { 00557 Registry::rootInstance().registerIt(std::make_pair(&typeid(Signature), function_name), (void *) function); 00558 } 00559 00573 static Signature *execute(const std::string &function_name) { 00574 Signature *user_function = (Signature *) Registry::rootInstance().getFunctionPtr(std::make_pair(&typeid(Signature), function_name)); 00575 00576 return (*user_function); 00577 } 00578 00592 static Signature *getFunction(const std::string &function_name) { 00593 Signature *user_function = (Signature *) Registry::rootInstance().getFunctionPtr(std::make_pair(&typeid(Signature), function_name)); 00594 00595 return user_function; 00596 } 00597 00608 static bool exists(const std::string &derived_name) { 00609 return Registry::rootInstance().getFuncPtr(std::make_pair(&typeid(Signature), derived_name)) != NULL; 00610 } 00611 00617 class Register 00618 { 00619 public: 00628 Register(const std::string &function_name, Signature *function) 00629 : m_function(function) 00630 { 00631 UserSubroutine<Signature>::instance().registerFunction(function_name, *m_function); 00632 } 00633 00634 private: 00635 Signature * m_function; 00636 }; 00637 }; 00638 00639 template <> 00640 void *Registry::getsym<void *>(const char *sym); 00641 00642 template <typename T> 00643 inline T Registry::getsym(const char *sym) { 00644 return static_cast<T>(getsym<void *>(sym)); 00645 } 00646 00647 } // namespace Plugin 00648 } // namespace sierra 00649 00650 typedef std::type_info *type_info_func(); 00651 00662 extern "C" { 00663 void SIERRA_FORTRAN(register_user_subroutine)( 00664 type_info_func type_id, 00665 void * user_subroutine, 00666 const char * name, 00667 int name_length ); 00668 } 00669 00670 00683 #define FORTRAN_USER_SUBROUTINE(NAME, USER_SUB) extern "C" const std::type_info * SIERRA_FORTRAN(NAME)() {return &typeid(USER_SUB::Signature);} 00684 00685 #endif // STK_UTIL_DIAG_UserPlugin_h