|
Sierra Toolkit
Version of the Day
|
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_classic::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_classic::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_classic::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_classic::diag::Writer & 00222 Registry::verbose_print( 00223 stk_classic::diag::Writer & dout) const 00224 { 00225 if (dout.shouldPrint()) { 00226 dout << "Registry, size " << getRegistryMap().size() << stk_classic::diag::push << stk_classic::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_classic::diag::dendl; 00230 dout << stk_classic::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