|
From: Prochnow, C. <pro...@se...> - 2005-05-18 14:27:57
|
Hi List,
i've rewritten the Factory and PluginManager! The old one had some problems
which could not be solved with the old implementation:
1) The first problem was that using Phoenix<> inside of a template leads to
different instances used by client- and library-code. We should keep that in
mind - never use Phoenix<> inline or inside of a template !!
2) The second problem was the FactoryInstanceHook code. I wondered why
Factory::create() could not create a type which should be dynamically loaded
by the PluginManager. After figuring out how the old code worked, i realized
that one had to use PuginManager::create() instead of Factory::create() to
make use of the "dynamically loadable types" feature, which was not feasible.
I remember, the goal was that Factory can create types that are dynamically
registered by shared libraries, without even knowing about shared libraries.
Ok, now the solution:
1) Instances of Factory are now kept by the FactoryBase class, which is
implemented in the library itself. Instances of Factory are retrieved and
created by a call to FactoryBase::instance(). FactoryBase::instance() uses a
callback to create an instance of the requested Factory
(Factory::createHook()).
2) FactoryBase holds a list of registered type-loader callbacks, which can be
registered via FactoryBase::registerLoader(). The type-loader callbacks are
called by Factory::create() whenever a type should be created, which is not
known to the Factory. This enables the PluginManager to register a
type-loader which tries to dynamically load types from shared libraries. The
PluginManager's type-loader is statically registered upon application init.
Some notes:
FactoryBase and PluginManager must distinguish between different Interface-
and Context-types, since these classes are non-templates, they use
type-strings obtained by a call to the RTTI typeid() function.
A draw-back is that the new Factory implementation does not support a variable
key-type, since it is not possible for the non-templated FactoryBase to have
variable key-types. Maybe we can re-introduce this feature, if it's really
needed, by using key-string's generated by LexT<>.
The Factory-class is now thread-safe. I added the CoreMutex class to get rid
of the dependency on the System-module in the AtomicTraits class, which
should be only used by classes in the core-module.
Example:
suppose we have a shared-library named "FileLogTarget.so" which implements the
LogTarget interface. The class inside the library is also named
"FileLogTarget".
// add directory where plugins are located
PluginManager::instance().addPluginDir<LogTarget>("./plugins");
// create an instance of FileLogTarget
LogTarget* target = Factory<LogTarget>::instance().create("FileLogTarget");
We now have an instance of the FileLogTarget class which got dynamically
registered by the shared-library, cool .. isnt it ?
With the old Factory and PluginManager code clients had to be aware that
FileLogTarget did come from a plugin and therefore had to use
PluginManager<LogTarget>::create() instead of Factory<LogTarget>::create().
Regards,
Christian
|