Sierra Toolkit Version of the Day
UserPlugin.hpp
Go to the documentation of this file.
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::diag::Writer &verbose_print(stk::diag::Writer &dout) const;
00306 };
00307 
00308 inline stk::diag::Writer &operator<<(stk::diag::Writer &dout, const Registry &registry) {
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines