Sierra Toolkit  Version of the Day
UserPlugin.cpp
1 
10 #include <stdexcept>
11 #include <sstream>
12 #include <string>
13 
15 #include <stk_util/diag/SlibDiagWriter.hpp>
16 
17 #ifdef SIERRA_DLOPEN_ENABLED
18 #include <dlfcn.h>
19 #endif
20 
21 namespace sierra {
22 namespace Plugin {
23 
24 std::string
25 derived_id_name(
26  int derived_id)
27 {
28  std::ostringstream derived_name;
29  derived_name << "enum id " << derived_id;
30  return derived_name.str();
31 }
32 
33 
35 Registry::getRegistryMap()
36 {
37  static RegistryMap s_registryMap;
38 
39  return s_registryMap;
40 }
41 
42 
43 Registry &
45 {
46  static Registry registry;
47 
48  return registry;
49 }
50 
51 
52 
53 void
55  const NamePair & name_pair,
56  void * func_ptr)
57 {
58  slibout.m(Slib::LOG_PLUGIN) << "Registering " << name_pair.second
59  << " of type " << demangle(name_pair.first->name())
60  << " at " << func_ptr << stk_classic::diag::dendl;
61 
62  RegistryMap::const_iterator registry_entry = getRegistryMap().find(name_pair);
63  if (registry_entry != getRegistryMap().end() && (*registry_entry).second != func_ptr) {
64  std::ostringstream strout;
65  strout << "Function with signature " << demangle((*registry_entry).first.first->name())
66  << " and derived name '" << (*registry_entry).first.second
67  << "' already registered to create function at address " << (*registry_entry).second;
68  throw std::invalid_argument(strout.str());
69  }
70  getRegistryMap()[name_pair] = func_ptr;
71 }
72 
73 
74 void *
76  const NamePair & name_pair) const
77 {
78  void *creator_function = getFuncPtr(name_pair);
79  if (creator_function)
80  return creator_function;
81  else {
82  std::ostringstream strout;
83 
84  strout << "User plugin creator function with base class '" << demangle(name_pair.first->name())
85  << "' and derived class name '" << name_pair.second
86  << "' not found in registry";
87  throw std::invalid_argument(strout.str());
88  }
89 }
90 
91 
92 void *
94  const NamePair & name_pair) const
95 {
96  void *creator_function = getFuncPtr(name_pair);
97  if (creator_function)
98  return creator_function;
99  else {
100  std::ostringstream strout;
101  strout << "User subroutine " << name_pair.second << "\n"
102  << " with signature " << demangle(name_pair.first->name()) << "\n"
103  << " not found in registry";
104  throw std::invalid_argument(strout.str());
105  }
106 }
107 
108 
109 Registry *
111  const NamePair & name_pair) const
112 {
113  Registry *creator_function = (Registry *) getFuncPtr(name_pair);
114  if (creator_function)
115  return creator_function;
116  else {
117  std::ostringstream strout;
118  strout << "Registry does not contain function with signature " << demangle(name_pair.first->name())
119  << " and derived name '" << name_pair.second << "'";
120  throw std::invalid_argument(strout.str());
121  }
122 }
123 
124 
125 void *
127  const NamePair & name_pair) const
128 {
129  RegistryMap::const_iterator registry_entry = getRegistryMap().find(name_pair);
130  return registry_entry == getRegistryMap().end() ? NULL : (*registry_entry).second;
131 }
132 
133 
134 std::vector<std::string>
136  const std::type_info & type) const
137 {
138  std::vector<std::string> derived_names;
139 
140  for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
141  if (*(*it).first.first == type)
142  derived_names.push_back((*it).first.second);
143 
144  return derived_names;
145 }
146 
147 
148 typedef void (*dl_register_t)();
149 
150 void
152  const char * so_path,
153  const char * function_name)
154 {
155 #ifdef SIERRA_DLOPEN_ENABLED
156  slibout.m(Slib::LOG_PLUGIN) << "Loading dynamic library " << so_path << stk_classic::diag::dendl;
157  void *dl = dlopen(so_path, RTLD_NOW);
158  if (!dl){
159  throw std::runtime_error(dlerror());
160  }
161 
162  if (function_name) {
163  std::string s = std::strlen(function_name) ? function_name : "dl_register";
164 
165  dl_register_t f = (dl_register_t) dlsym(dl, s.c_str());
166  if (!f) {
167  s = s + SIERRA_FORTRAN_SUFFIX;
168 
169  f = (dl_register_t) dlsym(dl, s.c_str());
170  }
171 
172  if (f) {
173  slibout.m(Slib::LOG_PLUGIN) << "Executing dynamic library " << so_path << " function " << s << "()" << stk_classic::diag::dendl;
174  (*f)();
175  }
176  else {
177  if (std::strlen(function_name)) {
178  std::ostringstream str;
179  str << "Registration function " << function_name << " not found in " << so_path;
180  throw std::runtime_error(str.str().c_str());
181  }
182  }
183  }
184 
185 #else
186  throw std::runtime_error("Dynamic linkage is not supported on this platform");
187 #endif
188 }
189 
190 
191 template <>
192 void *
193 Registry::getsym<void *>(
194  const char * sym)
195 {
196 #ifdef SIERRA_DLOPEN_ENABLED
197  void *s = NULL;
198  void *dl = dlopen(NULL, RTLD_LAZY);
199  if (dl) {
200  s = dlsym(dl, sym);
201  dlclose(dl);
202  }
203 
204  return s;
205 #else
206  return NULL;
207 #endif
208 }
209 
210 
211 std::ostream &
213  std::ostream & os) const
214 {
215  for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
216  os << (*it).first.second << " of type " << demangle((*it).first.first->name()) << " at " << (*it).second << std::endl;
217  return os;
218 }
219 
220 
224 {
225  if (dout.shouldPrint()) {
226  dout << "Registry, size " << getRegistryMap().size() << stk_classic::diag::push << stk_classic::diag::dendl;
227 
228  for (RegistryMap::const_iterator it = getRegistryMap().begin(); it != getRegistryMap().end(); ++it)
229  dout << (*it).first.second << " of type " << demangle((*it).first.first->name()) << " at " << (*it).second << stk_classic::diag::dendl;
231  }
232  return dout;
233 }
234 
235 
236 extern "C" {
237 
238 void SIERRA_FORTRAN(register_user_subroutine)(
239  type_info_func * type_id,
240  void * user_subroutine,
241  const char * name,
242  int name_len)
243 {
244  sierra::Plugin::Registry::rootInstance().registerIt(std::make_pair(type_id(), std::string(name, name_len)), user_subroutine);
245 }
246 
247 } // extern "C"
248 
249 } // namespace Plugin
250 } // namespace sierra
void SIERRA_FORTRAN() register_user_subroutine(type_info_func type_id, void *user_subroutine, const char *name, int name_length)
FORTRAN compatible user subprogram registration routine.
std::ostream & dout()
Diagnostic output stream.
Definition: OutputLog.cpp:674
Definition: Env.cpp:53
std::pair< const std::type_info *, std::string > NamePair
Typedef NamePair is the derived class key.
Definition: UserPlugin.hpp:63
static void registerDL(const char *so_path, const char *function_name=0)
Member function registerDL opens a dynamic library and optionally executes a "C" registration functio...
Definition: UserPlugin.cpp:151
Writer & pop(Writer &dout)
Member function pop calls the Writer::pop manipulator.
Definition: Writer.hpp:556
const char * demangle(const char *symbol)
Function demangle returns the demangled C++ symbol from the mangled C++ symbol. The mangled named is ...
Definition: Platform.cpp:210
std::ostream & verbose_print(std::ostream &os) const
Member function dump dumps the registry.
Definition: UserPlugin.cpp:212
void registerIt(const NamePair &name_pair, void *func_ptr)
Member function registerIt registers a name pair with a void pointer.
Definition: UserPlugin.cpp:54
void * getPluginPtr(const NamePair &name_pair) const
Member function getPluginPtr find the function with the name pair specified.
Definition: UserPlugin.cpp:75
Writer & dendl(Writer &dout)
Writer function dendl calls the Writer::dendl manipulator.
Definition: Writer.hpp:520
Class Writer implements a runtime selectable diagnostic output writer to aid in the development and d...
Definition: Writer.hpp:49
std::vector< std::string > getDerivedNames(const std::type_info &type) const
Member function getDerivedNames returns names assocaited with the function pointers of the specified ...
Definition: UserPlugin.cpp:135
void * getFuncPtr(const NamePair &name_pair) const
Member function getFuncPtr returns the function pointer with the specfied <it>name_pair.
Definition: UserPlugin.cpp:126
Registry * getFactoryPtr(const NamePair &name) const
Member function getFuncPtr returns the function pointer with the specfied <it>name_pair.
Definition: UserPlugin.cpp:110
std::map< NamePair, void *, less_nocase > RegistryMap
Typedef RegistryMap is the registration map.
Definition: UserPlugin.hpp:115
static Registry & rootInstance()
Member function rootInstance creates the singleton.
Definition: UserPlugin.cpp:44
Writer & push(Writer &dout)
Function push calls the Writer::push manipulator.
Definition: Writer.hpp:544
void * getFunctionPtr(const NamePair &name_pair) const
Member function getFunctionPtr find the function with the name pair specified.
Definition: UserPlugin.cpp:93