|
From: stephan b. <sg...@us...> - 2004-12-24 19:15:33
|
Update of /cvsroot/pclasses/pclasses2/include/pclasses/Plugin In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31255/include/pclasses/Plugin Added Files: Makefile.toc Plugin.h Log Message: egg --- NEW FILE: Makefile.toc --- #!/usr/bin/make -f include toc.make HEADERS = Plugin.h DIST_FILES += $(HEADERS) INSTALL_PACKAGE_HEADERS_DEST = $(prefix)/include/pclasses/Plugin INSTALL_PACKAGE_HEADERS += $(HEADERS) all: --- NEW FILE: Plugin.h --- #ifndef p_PLUGIN_HPP_INCLUDED #define p_PLUGIN_HPP_INCLUDED 1 #include <list> #include <string> #include "pclasses/pclasses-config.h" #include "pclasses/Factory.h" #include "pclasses/NonCopyable.h" #include "pclasses/System/SharedLib.h" #include "pclasses/System/PathFinder.h" #include "pclasses/System/Directory.h" namespace P { namespace Plugin { /** An internal helper type to clean up a list of pointers to objects. ContainterT must be compatible with list<T *> and calling 'delete Tobj' must be well-behaved. */ template <typename ContainterT> struct PluginCleaner : public ::P::NonCopyable { typedef ContainterT ListType; PluginCleaner() { } /** Calls delete() on each entry in container(). */ ~PluginCleaner() throw() { typename ListType::iterator it = m_list.begin(); while( m_list.end() != it ) { delete( (*it) ); ++it; } m_list.clear(); } /** Returns this object's container. */ ListType & container() { return this->m_list; } private: ListType m_list; }; /** PluginManager is an extended Factory type which attempts to provide a platform-neutral Plugin interface. Note that it inherits a "context type" from NamedTypeFactory, and shares factory maps with Factory<InterfaceT,string,ContextT>. The main implication of this is that one a PluginManager loads a plugin it may enable lower-level Factory objects to load types the plugin just loaded. */ template <class InterfaceT> class PluginManager : public ::P::NamedTypeFactory< InterfaceT >, public NonCopyable { public: typedef InterfaceT InterfaceType; typedef ::P::NamedTypeFactory< InterfaceT > ParentType; typedef PluginManager<InterfaceType> ThisType; /** Creates a PluginManager with a default search path and a platform-specific DLL file extension added to it's searchPath(). */ PluginManager() { this->init(); } /** When a PluginManager goes out of scope it deletes all SharedLib objects it opened via addPlugin(). The exact behaviour of this depends on the platform-specific SharedLib implementation. It is never safe to use symbols from a DLL once the DLL has been closed, but it is also impossible for us to track every single dll-registered symbol. Thus the safest thing to do is never use standlone PluginManager instances, and use the one available via instance() instead. */ virtual ~PluginManager() throw() { // reminder: m_holder goes out of scope // and cleans up it's container() now... } /** Adds dir to the lib search path. If dir does not exist then a RuntimeError will be thrown. */ void addPluginDir( const std::string & dir ) throw(::P::RuntimeError) { using ::P::System::Directory; const Directory d(dir); // throws on error d.begin(); // avoid 'unused var' warning. // ^^^ need to find a more elegant solution for that. this->searchPath().addPath( dir ); } /** Searches for so_name using searchPath(). If not found, a SystemError is thrown. If found, a SharedLib(filename) is created. If creation fails, a SystemError is thrown. On success a SharedLib pointer is returned. The caller does NOT own the pointer - it is owned by this class. @todo: if the SO is already opened, give back the existing SharedLib. We can't do this until we map names to SharedLibs, which we really have little reason to do. */ ::P::System::SharedLib * addPlugin( const std::string & so_name ) throw(::P::RuntimeError) { std::string fn = this->searchPath().find( so_name ); if( ! fn ) { throw ::P::SystemError( std::string("No plugin found for '")+so_name+"'.", P_SOURCEINFO ); } ::P::System::SharedLib * shl = ::P::System::openSharedLib( fn ); this->m_holder.container().push_back( shl ); return shl; } /** Returns a shared instance to an object of this type. Note that this shadows a static member of the same name in the base class! */ static ThisType & instance() { return ::P::Hook::FactoryInstanceHook<ThisType>::instance(); } /** This object's search path. Clients are free to modify it. */ ::P::System::PathFinder & searchPath() { return this->m_path; } /** This object's search path. */ const ::P::System::PathFinder & searchPath() const { return this->m_path; } /** A type used to hold SharedLib handles. */ typedef std::list< ::P::System::SharedLib * > PluginList; /** Returns the list of SharedLibs opened by this type. Clients should never destroy or close the libs in this list - they are owned by this class. A client may remove an entry from this list to take over ownership, but closing the lib may provide undefined results. If other parts of the program are still referencing memory which was once provided by the DLL, they will crash when they use it next. In practice it is safest to not close the DLLs and to let the OS do it at app shutdown. */ PluginList & sharedLibs() { return this->m_holder.container(); } const PluginList & sharedLibs() const { return this->m_holder.container(); } private: // PluginManager( const ThisType & ); // not impl. // ThisType & operator=( const ThisType & ); // not impl. void init() { this->m_path.addPath( "." ); this->m_path.addPath( PCLASSES_PLUGINS_DIR ); this->m_path.addPath( PCLASSES_LIB_DIR ); #ifdef __WIN32__ this->m_path.addExtension( ".dll" ); #else this->m_path.addExtension( ".so" ); #endif } PluginCleaner<PluginList> m_holder; ::P::System::PathFinder m_path; // ^^^^ todo: consider making this static. }; /** A convenience form of PluginManager<T>::instance(). */ template <typename T> PluginManager<T> & pluginManager() { return PluginManager<T>::instance(); } /** Convenience function to add a plugin dir to pluginManager<T>(). */ template <typename T> void addPluginDir( const std::string & path ) throw(RuntimeError) { return pluginManager<T>().addPluginDir( path ); } /** Convenience function to open a plugin using pluginManager<T>(). */ template <typename T> ::P::System::SharedLib * addPlugin( const std::string & ) throw(RuntimeError) { return pluginManager<T>().addPlugin( p ); } } } // namespace P:: Plugin #endif // p_PLUGIN_HPP_INCLUDED |