#include <Iguana/Framework/interface/IgModule.h>
Public Types | |
typedef InfoList::const_iterator | InfoIterator |
Public Member Functions | |
void | addInfo (IgPluginInfo *info, bool cache) |
virtual void | attach (void) |
virtual bool | attached (void) |
void | bad (bool value) |
Mark the module registration good or bad according to value. | |
bool | bad (void) const |
Check if the module registration has been marked bad. | |
InfoIterator | beginInfos (void) const |
IgModuleDescriptor * | cacheRoot (void) const |
virtual void | detach (void) |
void | detachInfo (IgPluginInfo *info) |
InfoIterator | endInfos (void) const |
IgModule (IgPluginManager *manager, const lat::Filename &libraryName, const std::string &time, const std::string &flag) | |
const lat::Filename & | libraryName (void) const |
virtual void | load (void) |
IgPluginManager * | manager (void) const |
virtual void | query (void) |
unsigned | time (void) const |
Return the registration file time stamp. | |
virtual void | unload (void) |
virtual | ~IgModule (void) |
Static Public Member Functions | |
static IgModule * | builtin (void) |
Protected Member Functions | |
virtual void | cache (IgModuleDescriptor *to) const |
Dump the contents of the module registration into the cache to. | |
IgModuleCapEntry | capabilityEntryPoint (void) |
virtual bool | checkEntryPoints (void) const |
void | clearCache (void) |
lat::SharedLibrary * | library (void) const |
bool | loaded (void) const |
void | makeCache (void) |
IgModuleEntry | moduleEntryPoint (void) |
virtual void | restore (IgModuleDescriptor *info) |
Static Protected Member Functions | |
static const char * | tag (void) |
Private Types | |
typedef std::list< IgPluginInfo * > | InfoList |
Private Member Functions | |
IgModule (const IgModule &) | |
IgModule & | operator= (const IgModule &) |
Private Attributes | |
bool | m_attached |
bool | m_bad |
IgModuleDescriptor * | m_cache |
IgModuleDef * | m_definition |
InfoList | m_infos |
lat::SharedLibrary * | m_library |
lat::Filename | m_libraryName |
IgPluginManager * | m_manager |
unsigned | m_time |
Static Private Attributes | |
static const char | s_capEntryPoint [] = "IGUANA_CAPABILITIES" |
static const char | s_modEntryPoint [] = "IGUANA_MODULE" |
static const char | s_tag [] = "module" |
Friends | |
class | IgModuleCache |
This class maintains the list of the capabilities provided by a plug-in module, but only in a generic manner. Custom plug-in factories provide access to specific information. The two are coordinated so that as new modules enter and leave the system the factory views are synchronised, and as new factories enter and leave, the information is cached and uncached automatically.
A IgModule exists for each module in an IgModuleCache regardless of whether the module library is presently loaded. The module is queried for the list of properties it provides (see IgModuleDef, DEFINE_IGUANA_MODULE, DEFINE_IGUANA_PLUGIN). IgModuleDirectory caches the information for later accesses without having to query the module. If the module changes, it us automatically queried again to update the cache.
IgModule can also treat the program itself as a module through the builtin() method. This allows dynamic loading to be bypassed as long as clients always use custom IgPluginManager factories and IgPluginLoader. Defining IGUANA_BUILTIN_PLUGINS preprocessor macro causes DEFINE_IGUANA_MODULE() and DEFINE_SEAL_PLUGIN() to a variant that automatically does so.
It is not safe to detach a module if there are any references remaining to it. This means there can be no live objects whose implementation for any part, including but not limited to virtual function tables, methods, template functions or static data, belong to the library detached. Note: this applies to any object created by the library, not just the plug-ins created by it!
For purposes of IgModuleCache the object remembers the time stamp of the module file when it was last examined, and whether it is good or bad. "Bad" means either that the file is corrupt in some way, for example the module could not be loaded.
Definition at line 69 of file IgModule.h.
typedef InfoList::const_iterator IgModule::InfoIterator |
Definition at line 73 of file IgModule.h.
typedef std::list<IgPluginInfo *> IgModule::InfoList [private] |
Definition at line 71 of file IgModule.h.
IgModule::IgModule | ( | IgPluginManager * | manager, | |
const lat::Filename & | libraryName, | |||
const std::string & | time, | |||
const std::string & | flag | |||
) |
Definition at line 43 of file IgModule.cc.
References ASSERT, LFplugin_manager, LOG, m_libraryName, makeCache(), and GsfMatrixTools::trace().
Referenced by builtin().
00047 : m_manager (manager), 00048 m_libraryName (libraryName), 00049 m_library (0), 00050 m_cache (0), 00051 m_time (strtoul (time.c_str (), 0, 10)), 00052 m_bad (flag != "good"), 00053 m_attached (libraryName.empty ()), 00054 m_definition (0) 00055 { 00056 ASSERT (flag == "good" || flag == "bad"); 00057 ASSERT (! time.empty ()); 00058 LOG (0, trace, LFplugin_manager, 00059 "constructing module for library `" << m_libraryName << "'\n"); 00060 makeCache (); 00061 }
IgModule::~IgModule | ( | void | ) | [virtual] |
Definition at line 63 of file IgModule.cc.
References ASSERT, LFplugin_manager, LOG, m_cache, m_infos, m_library, m_libraryName, GsfMatrixTools::trace(), and unload().
00064 { 00065 LOG (0, trace, LFplugin_manager, 00066 "destroying module for library `" << m_libraryName << "'\n"); 00067 00068 unload (); 00069 ASSERT (! m_library); 00070 00071 while (! m_infos.empty ()) 00072 delete *m_infos.begin (); 00073 00074 delete m_cache; 00075 }
IgModule::IgModule | ( | const IgModule & | ) | [private] |
void IgModule::addInfo | ( | IgPluginInfo * | info, | |
bool | cache | |||
) |
Definition at line 203 of file IgModule.cc.
References IgPluginManager::addInfo(), IgPluginInfo::cache(), cacheRoot(), m_infos, and m_manager.
Referenced by IgPluginInfo::finish().
00204 { 00205 if (needCache) 00206 // This info isn't cached yet -- add it. 00207 info->cache (cacheRoot ()); 00208 00209 m_infos.push_back (info); 00210 m_manager->addInfo (info); 00211 }
Definition at line 313 of file IgModule.cc.
References ASSERT, IgModuleDef::attach(), IgModuleDef::bind(), empty, IgPluginManager::feedback(), lat::indent(), LFplugin_manager, libraryName(), LOG, m_attached, m_definition, m_libraryName, m_manager, moduleEntryPoint(), IgPluginManager::StatusAttaching, GsfMatrixTools::trace(), and lat::undent().
00314 { 00315 if (! m_attached && ! libraryName ().empty ()) 00316 { 00317 ASSERT (! m_definition); 00318 00319 LOG (0, trace, LFplugin_manager, 00320 "attaching module " << libraryName () << '\n' << lat::indent); 00321 00322 // Capability-only modules don't have a normal entry; we 00323 // don't need a definition for them either. 00324 if (IgModuleEntry entry = moduleEntryPoint ()) 00325 { 00326 m_definition = (*entry) (); 00327 ASSERT (m_definition); 00328 00329 m_manager->feedback (IgPluginManager::StatusAttaching, m_libraryName); 00330 m_definition->bind (this); 00331 m_definition->attach (); 00332 } 00333 00334 m_attached = true; 00335 LOG (0, trace, LFplugin_manager, lat::undent); 00336 } 00337 }
Mark the module registration good or bad according to value.
Setting the value to true
resets the module contents.
Definition at line 94 of file IgModule.cc.
References clearCache(), and m_bad.
00095 { if ((m_bad = value)) clearCache (); }
Check if the module registration has been marked bad.
Definition at line 88 of file IgModule.cc.
References m_bad.
Referenced by makeCache().
00089 { return m_bad; }
IgModule::InfoIterator IgModule::beginInfos | ( | void | ) | const |
Definition at line 35 of file IgModule.cc.
References IgPluginManager::get(), and IgModule().
00036 { 00037 static IgModule *myself = new IgModule (IgPluginManager::get (), 00038 "" /* magic library name */, 00039 "0", "good"); 00040 return myself; 00041 }
void IgModule::cache | ( | IgModuleDescriptor * | to | ) | const [protected, virtual] |
Dump the contents of the module registration into the cache to.
Definition at line 238 of file IgModule.cc.
References IgModuleDescriptor::dup(), and m_cache.
00239 { 00240 // Internal cache is already in sync (we update it every time a 00241 // new info item is created), so let base class do all the work. 00242 m_cache->dup (to); 00243 }
IgModuleDescriptor * IgModule::cacheRoot | ( | void | ) | const |
Definition at line 190 of file IgModule.cc.
References m_cache.
Referenced by addInfo().
00191 { return m_cache; }
IgModuleCapEntry IgModule::capabilityEntryPoint | ( | void | ) | [protected] |
Definition at line 295 of file IgModule.cc.
References empty, lat::SharedLibrary::function(), LFplugin_manager, library(), libraryName(), LOG, s_capEntryPoint, and GsfMatrixTools::trace().
Referenced by query().
00296 { 00297 lat::SharedLibrary::Function entry = 0; 00298 00299 if (! libraryName ().empty ()) 00300 { 00301 // Swallow errors, just return null if it fails 00302 try { entry = library ()->function (s_capEntryPoint); } 00303 catch (lat::Error &) {} 00304 00305 LOG (0, trace, LFplugin_manager, "capability entry point (" 00306 << s_capEntryPoint << ") = " << (void *) entry << '\n'); 00307 } 00308 00309 return reinterpret_cast<IgModuleCapEntry> (entry); 00310 }
Definition at line 247 of file IgModule.cc.
References lat::Error::clone(), e, IgPluginManager::ErrorEntryFailure, IgPluginManager::feedback(), lat::SharedLibrary::function(), library(), m_libraryName, m_manager, s_capEntryPoint, s_modEntryPoint, and IgPluginManager::StatusEntries.
Referenced by load().
00248 { 00249 // Check for module entry points. It's legal to have just one or both 00250 // of the normal and capability entry points, but not to have neither. 00251 // First check for the capability entry point, then for the standard one. 00252 // If either succeeds, we declare success. If both fail, we record the 00253 // error from the standard entry point for more meaningful errors. 00254 m_manager->feedback (IgPluginManager::StatusEntries, m_libraryName); 00255 00256 try 00257 { 00258 if (library ()->function (s_capEntryPoint)) 00259 return true; 00260 } 00261 catch (lat::Error &) 00262 { 00263 } 00264 00265 try 00266 { 00267 return library ()->function (s_modEntryPoint); 00268 } 00269 catch (lat::Error &e) 00270 { 00271 m_manager->feedback (IgPluginManager::ErrorEntryFailure, m_libraryName, &e); 00272 throw IgPluginError (e.clone ()); 00273 } 00274 }
Definition at line 186 of file IgModule.cc.
References m_cache, and makeCache().
Referenced by bad(), and query().
Definition at line 340 of file IgModule.cc.
References IgModuleDef::detach(), empty, IgPluginManager::feedback(), i, lat::indent(), LFplugin_manager, libraryName(), loaded(), LOG, m_attached, m_definition, m_infos, m_libraryName, m_manager, IgModuleDef::release(), IgPluginManager::StatusDetaching, GsfMatrixTools::trace(), and lat::undent().
Referenced by unload().
00341 { 00342 if (loaded () && m_attached && ! libraryName ().empty ()) 00343 { 00344 LOG (0, trace, LFplugin_manager, 00345 "detaching module " << libraryName () << '\n' << lat::indent); 00346 00347 m_manager->feedback (IgPluginManager::StatusDetaching, m_libraryName); 00348 for (InfoIterator i = m_infos.begin (); i != m_infos.end (); ++i) 00349 (*i)->detach (); 00350 00351 // Capability-only modules don't have a definition. 00352 if (m_definition) 00353 { 00354 m_definition->detach (); 00355 m_definition->release (); 00356 m_definition = 0; 00357 } 00358 LOG (0, trace, LFplugin_manager, lat::undent); 00359 } 00360 }
void IgModule::detachInfo | ( | IgPluginInfo * | info | ) |
Definition at line 214 of file IgModule.cc.
References ASSERT, find(), m_infos, m_manager, and IgPluginManager::removeInfo().
Referenced by IgPluginInfo::~IgPluginInfo().
00215 { 00216 // Remove from the list but keep the details in the cache. Also 00217 // notify the plug-in database so that this gets removed from the 00218 // factories. 00219 InfoList::iterator pos = std::find (m_infos.begin (), m_infos.end (), info); 00220 ASSERT (pos != m_infos.end ()); 00221 m_infos.erase (pos); 00222 m_manager->removeInfo (info); 00223 }
IgModule::InfoIterator IgModule::endInfos | ( | void | ) | const |
lat::SharedLibrary * IgModule::library | ( | void | ) | const [protected] |
Definition at line 98 of file IgModule.cc.
References ASSERT, lat::Error::clone(), e, lat::Filename::empty(), IgPluginManager::ErrorLoadFailure, IgPluginManager::feedback(), LFplugin_manager, lat::SharedLibrary::load(), LOG, m_library, m_libraryName, m_manager, IgPluginManager::StatusLoading, and GsfMatrixTools::trace().
Referenced by capabilityEntryPoint(), checkEntryPoints(), load(), and moduleEntryPoint().
00099 { 00100 // FIXME: return SharedLibrary::self if m_libraryName is empty? 00101 if (m_libraryName.empty ()) 00102 return 0; 00103 00104 if (! m_library) 00105 { 00106 LOG (0, trace, LFplugin_manager, 00107 "loading shared library `" << m_libraryName << "'\n"); 00108 00109 try 00110 { 00111 m_manager->feedback (IgPluginManager::StatusLoading, m_libraryName); 00112 // FIXME: remove cast when filename is in the same namespace/gcc bug fixed 00113 m_library = lat::SharedLibrary::load ((const std::string &) m_libraryName); 00114 } 00115 catch (lat::Error &e) 00116 { 00117 m_manager->feedback (IgPluginManager::ErrorLoadFailure, m_libraryName, &e); 00118 throw IgPluginError (e.clone ()); 00119 } 00120 } 00121 00122 ASSERT (m_library); 00123 return m_library; 00124 }
const lat::Filename & IgModule::libraryName | ( | void | ) | const |
Definition at line 83 of file IgModule.cc.
References m_libraryName.
Referenced by attach(), capabilityEntryPoint(), detach(), moduleEntryPoint(), IgPluginInfo::noFactory(), IgModuleCache::FileByName::operator()(), and query().
00084 { return m_libraryName; }
Definition at line 131 of file IgModule.cc.
References checkEntryPoints(), lat::Filename::empty(), LFplugin_manager, library(), LOG, m_libraryName, GsfMatrixTools::trace(), and VERIFY.
00132 { 00133 if (m_libraryName.empty ()) 00134 return; 00135 00136 LOG (0, trace, LFplugin_manager, "loading `" << m_libraryName << "'\n"); 00137 00138 VERIFY (library ()); 00139 VERIFY (checkEntryPoints ()); 00140 }
Definition at line 127 of file IgModule.cc.
References lat::Filename::empty(), m_library, and m_libraryName.
Referenced by detach().
00128 { return m_libraryName.empty () || m_library;}
Definition at line 173 of file IgModule.cc.
References bad(), m_bad, m_cache, m_libraryName, m_time, lat::Filename::nondirectory(), s_tag, and time().
Referenced by clearCache(), and IgModule().
00174 { 00175 char time [40]; // 128+ bits 00176 const char *bad = m_bad ? "bad" : "good"; 00177 sprintf (time, "%lu", (unsigned long) m_time); 00178 00179 // Ask each module to dump itself under myself. 00180 m_cache = new IgModuleDescriptor (0, s_tag, 00181 m_libraryName.nondirectory ().name (), 00182 time, bad); 00183 }
IgPluginManager * IgModule::manager | ( | void | ) | const |
Definition at line 79 of file IgModule.cc.
References m_manager.
Referenced by IgPluginInfo::noFactory().
00080 { return m_manager; }
IgModuleEntry IgModule::moduleEntryPoint | ( | void | ) | [protected] |
Definition at line 277 of file IgModule.cc.
References empty, lat::SharedLibrary::function(), LFplugin_manager, library(), libraryName(), LOG, s_modEntryPoint, and GsfMatrixTools::trace().
Referenced by attach(), and query().
00278 { 00279 lat::SharedLibrary::Function entry = 0; 00280 00281 if (! libraryName ().empty ()) 00282 { 00283 // Swallow errors, just return null if it fails 00284 try { entry = library ()->function (s_modEntryPoint); } 00285 catch (lat::Error &) {} 00286 00287 LOG (0, trace, LFplugin_manager, "module entry point (" 00288 << s_modEntryPoint << ") = " << (void *) entry << '\n'); 00289 } 00290 00291 return reinterpret_cast<IgModuleEntry> (entry); 00292 }
Definition at line 363 of file IgModule.cc.
References ASSERT, IgModuleDef::bind(), capabilityEntryPoint(), clearCache(), IgPluginFactoryImplBase< Types >::declare(), empty, IgPluginManager::feedback(), IgPluginCapabilities::get(), i, lat::indent(), LFplugin_manager, libraryName(), LOG, m_definition, m_infos, m_libraryName, m_manager, moduleEntryPoint(), n, names, IgModuleDef::query(), IgModuleDef::release(), IgPluginManager::StatusQuerying, GsfMatrixTools::trace(), and lat::undent().
00364 { 00365 if (! libraryName ().empty ()) 00366 { 00367 ASSERT (! m_definition); 00368 00369 LOG (0, trace, LFplugin_manager, 00370 "querying module " << libraryName () << '\n' << lat::indent); 00371 00372 // Blast away existing infos and the cache in order to rebuild 00373 // a clean state from the newly created infos. 00374 clearCache (); 00375 while (! m_infos.empty ()) 00376 delete *m_infos.begin (); 00377 00378 // Now invoke the standard entry point. 00379 if (IgModuleEntry entry = moduleEntryPoint ()) 00380 { 00381 m_definition = (*entry) (); 00382 ASSERT (m_definition); 00383 00384 m_manager->feedback (IgPluginManager::StatusQuerying, m_libraryName); 00385 m_definition->bind (this); 00386 m_definition->query (); 00387 m_definition->release (); 00388 m_definition = 0; 00389 } 00390 00391 // Repeat with capabilities entry, processing it manually as 00392 // if the code was in the entry point in the module library. 00393 // This allows libraries to define "caability" modules with 00394 // pure string labels without linking against us -- but not 00395 // anything that needs a factory. These would normally be 00396 // used for side-effects or libraries that self-register to 00397 // some other factory. NB: The code below creates a module 00398 // definition even if the module has a standard entry point 00399 // and thus an existing definition. Since this is a query, 00400 // different defs don't matter, and attach will never use 00401 // the def anyway. 00402 if (IgModuleCapEntry capEntry = capabilityEntryPoint ()) 00403 { 00404 IgModuleDef *def = new IgModuleDef; 00405 const char **names = 0; 00406 int n = -1; 00407 00408 (*capEntry) (names, n); 00409 00410 def->bind (this); 00411 for (int i = 0; names && names [i] && (n < 0 || i < n); ++i) 00412 IgPluginCapabilities::get ()->declare (def, names [i]); 00413 def->release (); 00414 delete def; 00415 } 00416 00417 LOG (0, trace, LFplugin_manager, lat::undent); 00418 } 00419 }
void IgModule::restore | ( | IgModuleDescriptor * | info | ) | [protected, virtual] |
Definition at line 227 of file IgModule.cc.
References IgModuleDescriptor::dup(), m_cache, m_manager, and IgPluginManager::restore().
Referenced by IgModuleCache::reconstruct().
00228 { 00229 // FIXME: If factory is active, this will result in creation of a new 00230 // info, which we'll want to add to our cache. Make sure we don't 00231 // make duplicates... 00232 from->dup (m_cache); 00233 m_manager->restore (this, from); 00234 }
const char * IgModule::tag | ( | void | ) | [inline, static, protected] |
Definition at line 146 of file IgModule.h.
References s_tag.
Referenced by IgModuleCache::makeBad(), IgModuleCache::reconstruct(), and IgModuleCache::scanModules().
00147 { return s_tag; }
unsigned IgModule::time | ( | void | ) | const [inline] |
Return the registration file time stamp.
Definition at line 151 of file IgModule.h.
References m_time.
Referenced by makeCache().
00152 { return m_time; }
Definition at line 143 of file IgModule.cc.
References lat::SharedLibrary::abandon(), detach(), lat::Filename::empty(), IgPluginManager::feedback(), LFplugin_manager, LOG, m_library, m_libraryName, m_manager, lat::SharedLibrary::release(), IgPluginManager::StatusUnloading, and GsfMatrixTools::trace().
Referenced by ~IgModule().
00144 { 00145 if (m_libraryName.empty ()) 00146 return; 00147 00148 detach (); 00149 00150 // Do not unload libraries on platforms with broken handling of 00151 // global destructors in shared libraries (e.g. KCC 4.0f on 00152 // Linux). The problem is that global destructors are not 00153 // deregistered on library unload, causing instability with 00154 // subsequent dynamic loading operations, program exit etc. 00155 if (m_library) 00156 { 00157 LOG (0, trace, LFplugin_manager, "unloading `" << m_libraryName << "'\n"); 00158 00159 if (lat::ShellEnvironment ().has ("IGUANA_RELEASE_MODULES")) 00160 { 00161 m_manager->feedback (IgPluginManager::StatusUnloading, m_libraryName); 00162 m_library->release (); 00163 } 00164 else 00165 m_library->abandon (); 00166 00167 m_library = 0; 00168 } 00169 }
friend class IgModuleCache [friend] |
Definition at line 107 of file IgModule.h.
bool IgModule::m_attached [private] |
bool IgModule::m_bad [private] |
IgModuleDescriptor* IgModule::m_cache [private] |
Definition at line 126 of file IgModule.h.
Referenced by cache(), cacheRoot(), clearCache(), makeCache(), restore(), and ~IgModule().
IgModuleDef* IgModule::m_definition [private] |
InfoList IgModule::m_infos [private] |
Definition at line 132 of file IgModule.h.
Referenced by addInfo(), beginInfos(), detach(), detachInfo(), endInfos(), query(), and ~IgModule().
lat::SharedLibrary* IgModule::m_library [mutable, private] |
Definition at line 125 of file IgModule.h.
Referenced by library(), loaded(), unload(), and ~IgModule().
lat::Filename IgModule::m_libraryName [private] |
Definition at line 124 of file IgModule.h.
Referenced by attach(), checkEntryPoints(), detach(), IgModule(), library(), libraryName(), load(), loaded(), makeCache(), query(), unload(), and ~IgModule().
IgPluginManager* IgModule::m_manager [private] |
Definition at line 123 of file IgModule.h.
Referenced by addInfo(), attach(), checkEntryPoints(), detach(), detachInfo(), library(), manager(), query(), restore(), and unload().
unsigned IgModule::m_time [private] |
const char IgModule::s_capEntryPoint = "IGUANA_CAPABILITIES" [static, private] |
Definition at line 134 of file IgModule.h.
Referenced by capabilityEntryPoint(), and checkEntryPoints().
const char IgModule::s_modEntryPoint = "IGUANA_MODULE" [static, private] |
Definition at line 133 of file IgModule.h.
Referenced by checkEntryPoints(), and moduleEntryPoint().
const char IgModule::s_tag = "module" [static, private] |