Sierra Toolkit Version of the Day
UserPlugin.cpp
00001 
00010 #include <stdexcept>
00011 #include <sstream>
00012 #include <string>
00013 
00014 #include <stk_util/diag/UserPlugin.hpp>
00015 #include <stk_util/diag/SlibDiagWriter.hpp>
00016 
00017 #ifdef SIERRA_DLOPEN_ENABLED
00018 #include <dlfcn.h>
00019 #endif
00020 
00021 namespace sierra {
00022 namespace Plugin {
00023 
00024 std::string
00025 derived_id_name(
00026   int     derived_id)
00027 {
00028   std::ostringstream derived_name;
00029   derived_name << "enum id " << derived_id;
00030   return derived_name.str();
00031 }
00032 
00033 
00034 Registry::RegistryMap &
00035 Registry::getRegistryMap()
00036 {
00037   static RegistryMap s_registryMap;
00038 
00039   return s_registryMap;
00040 }
00041 
00042 
00043 Registry &
00044 Registry::rootInstance()
00045 {
00046   static Registry registry;
00047 
00048   return registry;
00049 }
00050 
00051 
00052 
00053 void
00054 Registry::registerIt(
00055   const NamePair &  name_pair,
00056   void *    func_ptr)
00057 {
00058   slibout.m(Slib::LOG_PLUGIN) << "Registering " << name_pair.second
00059             << " of type " << demangle(name_pair.first->name())
00060             << " at " << func_ptr << stk::diag::dendl;
00061 
00062   RegistryMap::const_iterator registry_entry = getRegistryMap().find(name_pair);
00063   if (registry_entry != getRegistryMap().end() && (*registry_entry).second != func_ptr) {
00064     std::ostringstream strout;
00065     strout << "Function with signature " << demangle((*registry_entry).first.first->name())
00066      << " and derived name '" << (*registry_entry).first.second
00067      << "' already registered to create function at address " << (*registry_entry).second;
00068     throw std::invalid_argument(strout.str());
00069   }
00070   getRegistryMap()[name_pair] = func_ptr;
00071 }
00072 
00073 
00074 void *
00075 Registry::getPluginPtr(
00076   const NamePair &  name_pair) const
00077 {
00078   void *creator_function = getFuncPtr(name_pair);
00079   if (creator_function)
00080     return creator_function;
00081   else {
00082     std::ostringstream strout;
00083 
00084     strout << "User plugin creator function with base class '" << demangle(name_pair.first->name())
00085      << "' and derived class name '" << name_pair.second
00086      << "' not found in registry";
00087     throw std::invalid_argument(strout.str());
00088   }
00089 }
00090 
00091 
00092 void *
00093 Registry::getFunctionPtr(
00094   const NamePair &  name_pair) const
00095 {
00096   void *creator_function = getFuncPtr(name_pair);
00097   if (creator_function)
00098     return creator_function;
00099   else {
00100     std::ostringstream strout;
00101     strout << "User subroutine " << name_pair.second << "\n"
00102      << " with signature " << demangle(name_pair.first->name()) << "\n"
00103            << " not found in registry";
00104     throw std::invalid_argument(strout.str());
00105   }
00106 }
00107 
00108 
00109 Registry *
00110 Registry::getFactoryPtr(
00111   const NamePair &  name_pair) const
00112 {
00113   Registry *creator_function = (Registry *) getFuncPtr(name_pair);
00114   if (creator_function)
00115     return creator_function;
00116   else {
00117     std::ostringstream strout;
00118     strout << "Registry does not contain function with signature " << demangle(name_pair.first->name())
00119      << " and derived name '" << name_pair.second << "'";
00120     throw std::invalid_argument(strout.str());
00121   }
00122 }
00123 
00124 
00125 void *
00126 Registry::getFuncPtr(
00127   const NamePair &  name_pair) const
00128 {
00129   RegistryMap::const_iterator registry_entry = getRegistryMap().find(name_pair);
00130   return registry_entry == getRegistryMap().end() ? NULL : (*registry_entry).second;
00131 }
00132 
00133 
00134 std::vector<std::string>
00135 Registry::getDerivedNames(
00136   const std::type_info &  type) const
00137 {
00138   std::vector<std::string> derived_names;
00139 
00140   for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
00141     if (*(*it).first.first == type)
00142       derived_names.push_back((*it).first.second);
00143 
00144   return derived_names;
00145 }
00146 
00147 
00148 typedef void (*dl_register_t)();
00149 
00150 void
00151 Registry::registerDL(
00152   const char *    so_path,
00153   const char *    function_name)
00154 {
00155 #ifdef SIERRA_DLOPEN_ENABLED
00156   slibout.m(Slib::LOG_PLUGIN) << "Loading dynamic library " << so_path << stk::diag::dendl;
00157   void *dl = dlopen(so_path, RTLD_NOW);
00158   if (!dl){
00159     throw std::runtime_error(dlerror());
00160   }
00161   
00162   if (function_name) {
00163     std::string s = std::strlen(function_name) ? function_name : "dl_register";
00164     
00165     dl_register_t f = (dl_register_t) dlsym(dl, s.c_str());
00166     if (!f) {
00167       s = s + SIERRA_FORTRAN_SUFFIX;
00168       
00169       f = (dl_register_t) dlsym(dl, s.c_str());
00170     }
00171     
00172     if (f) {
00173       slibout.m(Slib::LOG_PLUGIN) << "Executing dynamic library " << so_path << " function " << s << "()" << stk::diag::dendl;
00174       (*f)();
00175     }
00176     else {
00177       if (std::strlen(function_name)) {
00178         std::ostringstream str;
00179         str << "Registration function " << function_name << " not found in " << so_path;
00180         throw std::runtime_error(str.str().c_str());
00181       }
00182     }
00183   }
00184   
00185 #else
00186   throw std::runtime_error("Dynamic linkage is not supported on this platform");
00187 #endif
00188 }
00189 
00190 
00191 template <>
00192 void *
00193 Registry::getsym<void *>(
00194   const char *  sym)
00195 {
00196 #ifdef SIERRA_DLOPEN_ENABLED
00197   void *s = NULL;
00198   void *dl = dlopen(NULL, RTLD_LAZY);
00199   if (dl) {
00200     s = dlsym(dl, sym);
00201     dlclose(dl);
00202   }
00203 
00204   return s;
00205 #else
00206   return NULL;
00207 #endif
00208 }
00209 
00210 
00211 std::ostream &
00212 Registry::verbose_print(
00213   std::ostream &    os) const
00214 {
00215   for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
00216     os << (*it).first.second << " of type " << demangle((*it).first.first->name()) << " at " << (*it).second << std::endl;
00217   return os;
00218 }
00219 
00220 
00221 stk::diag::Writer &
00222 Registry::verbose_print(
00223   stk::diag::Writer &   dout) const
00224 {
00225   if (dout.shouldPrint()) {
00226     dout << "Registry, size " << getRegistryMap().size() << stk::diag::push << stk::diag::dendl;
00227 
00228     for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
00229       dout << (*it).first.second << " of type " << demangle((*it).first.first->name()) << " at " << (*it).second << stk::diag::dendl;
00230     dout << stk::diag::pop;
00231   }
00232   return dout;
00233 }
00234 
00235 
00236 extern "C" {
00237 
00238 void SIERRA_FORTRAN(register_user_subroutine)(
00239   type_info_func *    type_id,
00240   void *      user_subroutine,
00241   const char *      name,
00242   int       name_len)
00243 {
00244   sierra::Plugin::Registry::rootInstance().registerIt(std::make_pair(type_id(), std::string(name, name_len)), user_subroutine);
00245 }
00246 
00247 } // extern "C"
00248 
00249 } // namespace Plugin
00250 } // namespace sierra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines