📄 plugin_manager.hpp
字号:
/* * =========================================================================== * PRODUCTION $Log: plugin_manager.hpp,v $ * PRODUCTION Revision 1000.7 2004/06/01 19:08:16 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.22 * PRODUCTION * =========================================================================== */#ifndef CORELIB___PLUGIN_MANAGER__HPP#define CORELIB___PLUGIN_MANAGER__HPP/* $Id: plugin_manager.hpp,v 1000.7 2004/06/01 19:08:16 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Denis Vakatov, Anatoliy Kuznetsov * * File Description: Plugin manager (using class factory paradigm) * *//// @file plugin_manager.hpp/// Plugin manager (using class factory paradigm).////// Describe generic interface and provide basic functionality to advertise/// and export a class factory. /// The class and class factory implementation code can be linked to/// either statically (then, the class factory will need to be registered/// explicitly by the user code) or dynamically (then, the DLL will be/// searched for using plugin name, and the well-known DLL entry point/// will be used to register the class factory, automagically)./// /// - "class factory" -- An entity used to generate objects of the given class./// One class factory can generate more than one version/// of the class./// /// - "interface" -- Defines the implementation-independent API and expected/// behaviour of a class./// Interface's name is provided by its class's factory,/// see IClassFactory::GetInterfaceName()./// Interfaces are versioned to track the compatibility./// /// - "driver" -- A concrete implementation of the interface and its factory./// Each driver has its own name (do not confuse it with the/// interface name!) and version./// /// - "host" -- An entity (DLL or the EXEcutable itself) that contains/// one or more drivers (or versions of the same driver),/// which can implement one or more interfaces./// /// - "version" -- MAJOR (backward- and forward-incompatible changes in the/// interface and/or its expected behaviour);/// MINOR (backward compatible changes in the driver code);/// PATCH_LEVEL (100% compatible plugin or driver code changes)./// #include <corelib/ncbimtx.hpp>#include <corelib/version.hpp>#include <corelib/ncbidll.hpp>#include <corelib/ncbi_tree.hpp>#include <set>#include <string>BEGIN_NCBI_SCOPE/** @addtogroup PluginMgr * * @{ *//////////////////////////////////////////////////////////////////////////////////// CPluginManagerException --////// Exception generated by CPluginManager.class NCBI_XNCBI_EXPORT CPluginManagerException : public CCoreException{public: /// Error types that CTime can generate. enum EErrCode { eResolveFailure ///< Cannot resolve interface driver }; /// Translate from the error code value to its string representation. virtual const char* GetErrCodeString(void) const { switch (GetErrCode()) { case eResolveFailure: return "eResolveFailure"; default: return CException::GetErrCodeString(); } } // Standard exception boilerplate code. NCBI_EXCEPTION_DEFAULT(CPluginManagerException, CCoreException);};/// CInterfaceVersion<> --////// Current interface version.////// It is just a boilerplate, to be hard-coded in the concrete interface header/// @sa NCBI_PLUGIN_VERSION, CVersionInfotemplate <class TClass>class CInterfaceVersion{};/// Macro to auto-setup the current interface name and version.////// This macro must be "called" once per interface, usually in the/// very header that describes that interface.////// Example:/// NCBI_INTERFACE_VERSION(IFooBar, "IFooBar", 1, 3, 8);/// @sa CInterfaceVersion#define NCBI_DECLARE_INTERFACE_VERSION(iface, iface_name, major, minor, patch_level) \template<> \class CInterfaceVersion<iface> \{ \public: \ enum { \ eMajor = major, \ eMinor = minor, \ ePatchLevel = patch_level \ }; \ static const char* GetName() { return iface_name; } \}/// Macro to contruct CVersionInfo class using interface name/// (relies on CInterfaceVersion class)/// @sa CVersionInfo#define NCBI_INTERFACE_VERSION(iface) \CVersionInfo(ncbi::CInterfaceVersion<iface>::eMajor, \ ncbi::CInterfaceVersion<iface>::eMinor, \ ncbi::CInterfaceVersion<iface>::ePatchLevel)/// Instantiation parameters tree.typedef CTreePairNode<string, string> TPluginManagerParamTree;/// IClassFactory<> --////// Class factory for the given interface.////// IClassFactory should be implemented for collection of drivers/// and exported by hoststemplate <class TClass, class TIfVer = CInterfaceVersion<TClass> >class IClassFactory{public: typedef TClass TInterface; struct SDriverInfo { string name; ///< Driver name CVersionInfo version; ///< Driver version SDriverInfo(const string& driver_name, const CVersionInfo& driver_version) : name(driver_name), version(driver_version) {} }; typedef list<SDriverInfo> TDriverList; /// Create driver's instance /// /// Function creates driver by its name and version. /// The requirements is the drivers version should match the interface /// up to the patch level. /// /// @param driver /// Requested driver's name (not the name of the supported interface) /// @param version /// Requested interface version (as understood by the caller). /// By default it will be passed the version which is current from /// the calling code's point of view. /// @param /// @return /// NULL on any error (not found entry point, version mismatch, etc.) virtual TClass* CreateInstance (const string& driver = kEmptyStr, CVersionInfo version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor, TIfVer::ePatchLevel), const TPluginManagerParamTree* params = 0) const = 0; /// Versions of the interface exported by the factory virtual void GetDriverVersions(TDriverList& driver_list) const = 0; virtual ~IClassFactory(void) {}};class CPluginManager_DllResolver;/// CPluginManager<> --////// To register (either directly, or via an "entry point") class factories/// for the given interface.////// Then, to facilitate the process of instantiating the class given/// the registered pool of drivers, and also taking into accont the driver name/// and/or version as requested by the calling code.////// Template class is protected by mutex and safe for use from diffrent threadstemplate <class TClass, class TIfVer = CInterfaceVersion<TClass> >class CPluginManager{public: typedef IClassFactory<TClass, TIfVer> TClassFactory; /// Create class instance /// @return /// Never returns NULL -- always throw exception on error. /// @sa GetFactory() TClass* CreateInstance (const string& driver = kEmptyStr, const CVersionInfo& version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor, TIfVer::ePatchLevel), const TPluginManagerParamTree* params = 0) { TClassFactory* factory = GetFactory(driver, version); return factory->CreateInstance(driver, version, params); } /// Get class factory /// /// If more than one (of registered) class factory contain eligible /// driver candidates, then pick the class factory containing driver of /// the latest version. /// @param driver /// Name of the driver. If passed empty, then -- any. /// @param version /// Requested version. The returned driver can have a different (newer) /// version (provided that the new implementation is backward-compatible /// with the requested version. /// @return /// Never return NULL -- always throw exception on error. TClassFactory* GetFactory (const string& driver = kEmptyStr, const CVersionInfo& version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor, TIfVer::ePatchLevel)); /// Information about a driver, with maybe a pointer to an instantiated /// class factory that contains the driver. /// @sa FNCBI_EntryPoint struct SDriverInfo { string name; ///< Driver name CVersionInfo version; ///< Driver version // It's the plugin manager's (and not SDriverInfo) responsibility to // keep and then destroy class factories. TClassFactory* factory; ///< Class factory (can be NULL) SDriverInfo(const string& driver_name, const CVersionInfo& driver_version) : name(driver_name), version(driver_version), factory(0) {} }; /// List of driver information. /// /// It is used to communicate using the entry points mechanism. /// @sa FNCBI_EntryPoint typedef list<SDriverInfo> TDriverInfoList; /// Register factory in the manager. /// /// The registered factory will be owned by the manager. /// @sa UnregisterFactory() void RegisterFactory(TClassFactory& factory); /// Unregister and release (un-own) /// @sa RegisterFactory() bool UnregisterFactory(TClassFactory& factory); /// Actions performed by the entry point /// @sa FNCBI_EntryPoint enum EEntryPointRequest { /// Add info about all drivers exported through the entry point /// to the end of list. /// /// "SFactoryInfo::factory" in the added info should be assigned NULL. eGetFactoryInfo, /// Scan the driver info list passed to the entry point for the /// [name,version] pairs exported by the given entry point. /// /// For each pair found, if its "SDriverInfo::factory" is NULL, /// instantiate its class factory and assign it to the /// "SDriverInfo::factory". eInstantiateFactory }; /// Entry point to get drivers' info, and (if requested) their class /// factori(es). /// /// This function is usually (but not necessarily) called by /// RegisterWithEntryPoint(). /// /// Usually, it's called twice -- the first time to get the info /// about the drivers exported by the entry point, and then /// to instantiate selected factories. /// /// Caller is responsible for the proper destruction (deallocation) /// of the instantiated factories. typedef void (*FNCBI_EntryPoint)(TDriverInfoList& info_list, EEntryPointRequest method); /// Register all factories exported by the plugin entry point. /// @sa RegisterFactory() void RegisterWithEntryPoint(FNCBI_EntryPoint plugin_entry_point); /// Attach DLL resolver to plugin manager /// /// Plugin mananger uses all attached resolvers to search for DLLs /// exporting drivers of this interface. /// /// @param resolver /// DLL resolver. Plugin manager takes ownership of the resolver. /// /// @sa DetachResolver void AddResolver(CPluginManager_DllResolver* resolver); /// Remove resolver from the list of active resolvers. /// /// Method is used when we need to freeze some of the resolution variants /// Resolver is not deleted, and can be reattached again by AddResolver /// /// @param resolver /// DLL resolver. Ownership is returned to the caller and resolver /// should be deleted by the caller /// /// @return Pointer on the detached resolver (same as resolver parameter) /// or NULL if resolver not found CPluginManager_DllResolver* DetachResolver(CPluginManager_DllResolver* resolver); /// Add path for the DLL lookup (for all resolvers) void AddDllSearchPath(const string& path); /// Scan DLLs for specified driver using attached resolvers void Resolve(const string& driver = kEmptyStr, const CVersionInfo& version = CVersionInfo (TIfVer::eMajor, TIfVer::eMinor, TIfVer::ePatchLevel)); /// Disable/enable DLL resolution (search for class factories in DLLs) void FreezeResolution(bool value = true) { m_BlockResolution = value; } /// Disable/enable DLL resolution (search for class factories in DLLs) /// for the specified driver void FreezeResolution(const string& driver, bool value = true); // ctors CPluginManager(void) : m_BlockResolution(false) {} virtual ~CPluginManager();protected: TClassFactory* FindClassFactory(const string& driver, const CVersionInfo& version); /// Protective mutex to syncronize the access to the plugin manager /// from different threads CFastMutex m_Mutex; typedef vector<CDllResolver::SResolvedEntry> TResolvedEntries; typedef vector<CPluginManager_DllResolver*> TDllResolvers; typedef set<string> TStringSet;private: /// List of factories presently registered with (and owned by) /// the plugin manager. set<TClassFactory*> m_Factories; /// DLL resolvers TDllResolvers m_Resolvers; /// Paths used for DLL search vector<string> m_DllSearchPaths; /// DLL entries resolved and registered with dll resolver(s) TResolvedEntries m_RegisteredEntries; /// Flag, prohibits DLL resolution bool m_BlockResolution; /// Set of drivers prohibited from DLL resolution TStringSet m_FreezeResolutionDrivers;};/// Service class for DLLs resolution./// /// Class is used by CPluginManager to scan directories for DLLs, /// load and resolve entry points.///class NCBI_XNCBI_EXPORT CPluginManager_DllResolver{public: // CPluginManager_DllResolver(void); /// Construction ///
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -