/usr/include/arc/loader/ModuleManager.h is in nordugrid-arc-dev 5.0.5-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #ifndef __ARC_MODULEMANAGER_H__
#define __ARC_MODULEMANAGER_H__
#include <string>
#include <map>
#include <list>
#include <glibmm/module.h>
#include <arc/XMLNode.h>
#include <arc/Thread.h>
#include <arc/Logger.h>
namespace Arc {
class ModuleManager;
/// If found in loadable module this function is called
/// right after module is loaded. It provides functionality
/// similar to constructor attribute of GCC, but is independent
/// of compiler and gives access to manager and module objects.
#define ARC_MODULE_CONSTRUCTOR_NAME __arc_module_constructor__
#define ARC_MODULE_CONSTRUCTOR_SYMB "__arc_module_constructor__"
typedef void (*arc_module_constructor_func)(Glib::Module*, ModuleManager*);
/// If found in loadable module this function is called
/// right before module is unloaded. It provides functionality
/// similar to constructor attribute of GCC, but is independent
/// of compiler and gives access to manager and module objects.
/// If module was set as persistent this function is still called
/// although module is not actually unloaded.
#define ARC_MODULE_DESTRUCTOR_NAME __arc_module_destructor__
#define ARC_MODULE_DESTRUCTOR_SYMB "__arc_module_destructor__"
typedef void (*arc_module_destructor_func)(Glib::Module*, ModuleManager*);
/// Manager of shared libraries
/** This class loads shared libraries/modules.
There supposed to be created one instance of it per executable.
In such circumstances it would cache handles to loaded modules
and not load them multiple times. But creating multiple instances
is not prohibited.
Instance of this class handles loading of shared libraries through
call to load() method. All loaded libraries are remembered internally
and by default are unloaded when instance of this class is destroyed.
Sometimes it is not safe to unload library. In such case makePersistent()
for this library must be called.
Upon first load() of library ModuleManager looks for function called
__arc_module_constructor__ and calls it. This makes it possible for
library to do some preparations. Currently it is used to make some
libraries persistent in memory.
Before unloading library from memory __arc_module_destructor__ is
called if present.
Every loaded library has load counter associated. Each call to
load() for specific library increases that counter and unload() decreases
it. Library is unloaded when counter reaches zero. When instance of
ModuleManager is destroyed all load counters are reset to 0 and libraries
are unloaded unless claimed to stay persistent in memory.
Each library also has usage counter associated. Those counters are increased
and decreased by use() and unuse() methods. This counter is used to claim usage
of code provided by loaded library. It is automatically increased and decreased
in constructor and destructor of Plugin class. Having non-zero usage counter
prevents library from being unloaded.
Please note that destructor of ModuleManager waits for all usage counters to
reach zero. This is especially useful in multithreaded environments. To avoid
dealocks make sure Plugins loaded by instance of ModuleManager are destroyed
before destroying ModuleManager or in independent threads.
*/
class ModuleManager
{
private:
class LoadableModuleDescription {
private:
Glib::Module* module;
int count;
int usage_count;
std::string path;
void check_unload(ModuleManager* manager);
public:
LoadableModuleDescription(void);
LoadableModuleDescription(Glib::Module* m);
LoadableModuleDescription& operator=(Glib::Module* m);
LoadableModuleDescription& operator=(const LoadableModuleDescription& d);
operator Glib::Module*(void) { return module; };
operator bool(void) { return (module != NULL); };
bool operator!(void) { return (module == NULL); };
bool operator==(Glib::Module* m) { return (module==m); };
int load(void);
int unload(ModuleManager* manager);
int use(void) { ++usage_count; return usage_count; };
int unuse(void) {
if(usage_count > 0) --usage_count;
//check_unload(); - not unloading code because it is needed at least to do return.
return usage_count;
};
int usage(void) { return usage_count; };
void makePersistent(void) { if(module) module->make_resident(); };
};
friend class LoadableModuleDescription;
typedef std::map<std::string, LoadableModuleDescription> plugin_cache_t;
Glib::Mutex mlock;
static Logger logger;
std::list<std::string> plugin_dir; /** collection of path to directory for modules */
plugin_cache_t plugin_cache; /** Cache of handles of loaded modules */
ModuleManager(const ModuleManager&) {};
ModuleManager& operator=(const ModuleManager&) { return *this; };
protected:
/** Unload module by its identifier.
Decreases load counter and unloads module when it reaches 0. */
void unload(Glib::Module* module);
/** Unload module by its name */
void unload(const std::string& name);
public:
/** Constructor.
It is supposed to process correponding configuration subtree
and tune module loading parameters accordingly. */
ModuleManager(XMLNode cfg);
~ModuleManager();
/** Finds module 'name' in cache or loads corresponding loadable module */
Glib::Module* load(const std::string& name,bool probe);
/** Finds loadable module by 'name' looking in
same places as load() does, but does not load it. */
std::string find(const std::string& name);
/** Reload module previously loaded in probe mode.
New module is loaded with all symbols resolved and
old module handler is unloaded. In case of error old
module is not unloaded. */
Glib::Module* reload(Glib::Module* module);
/** Increase usage count of loaded module.
It is intended to be called by plugins or other code which
needs prevent module to be unloaded while its code is running.
Must be accompanied by unuse when module is not needed. */
void use(Glib::Module* module);
/** Decrease usage count till it reaches 0.
This call does not unload module. Usage counter is only for
preventing unexpected unload. Unloading is done by unload()
methods and by desctructor if usage counter is zero. */
void unuse(Glib::Module* module);
/** Finds shared library corresponding to module 'name' and returns path to it */
std::string findLocation(const std::string& name);
/** Make sure this module is never unloaded. Even if unload() is called.
Call to this method does not affect how other methods arel behaving.
Just loaded module stays in memory after all unloading procedures. */
bool makePersistent(Glib::Module* module);
/** Make sure this module is never unloaded. Even if unload() is called. */
bool makePersistent(const std::string& name);
/** Input the configuration subtree, and trigger the module loading (do almost
the same as the Constructor).
This method is desigined for ClassLoader to adopt the singleton pattern. */
void setCfg (XMLNode cfg);
};
} // namespace Arc
#endif /* __ARC_MODULEMANAGER_H__ */
|