📄 classloader.h
字号:
//// ClassLoader.h//// $Id: //poco/1.2/Foundation/include/Poco/ClassLoader.h#1 $//// Library: Foundation// Package: SharedLibrary// Module: ClassLoader//// Definition of the ClassLoader class.//// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.// and Contributors.//// Permission is hereby granted, free of charge, to any person or organization// obtaining a copy of the software and accompanying documentation covered by// this license (the "Software") to use, reproduce, display, distribute,// execute, and transmit the Software, and to prepare derivative works of the// Software, and to permit third-parties to whom the Software is furnished to// do so, all subject to the following:// // The copyright notices in the Software and this entire statement, including// the above license grant, this restriction and the following disclaimer,// must be included in all copies of the Software, in whole or in part, and// all derivative works of the Software, unless such copies or derivative// works are solely in the form of machine-executable object code generated by// a source language processor.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE.//#ifndef Foundation_ClassLoader_INCLUDED#define Foundation_ClassLoader_INCLUDED#include "Poco/Foundation.h"#include "Poco/MetaObject.h"#include "Poco/Manifest.h"#include "Poco/SharedLibrary.h"#include "Poco/Mutex.h"#include "Poco/Exception.h"#include <map>namespace Poco {template <class Base>class ClassLoader /// The ClassLoader loads C++ classes from shared libraries /// at runtime. It must be instantiated with a root class /// of the loadable classes. /// For a class to be loadable from a library, the library /// must provide a Manifest of all the classes it contains. /// The Manifest for a shared library can be easily built /// with the help of the macros in the header file /// "Foundation/ClassLibrary.h".{public: typedef AbstractMetaObject<Base> Meta; typedef Manifest<Base> Manif; typedef void (*InitializeLibraryFunc)(); typedef void (*UninitializeLibraryFunc)(); typedef bool (*BuildManifestFunc)(ManifestBase*); struct LibraryInfo { SharedLibrary* pLibrary; const Manif* pManifest; int refCount; }; typedef std::map<std::string, LibraryInfo> LibraryMap; class Iterator /// The ClassLoader's very own iterator class. { public: typedef std::pair<std::string, const Manif*> Pair; Iterator(const typename LibraryMap::const_iterator& it) { _it = it; } Iterator(const Iterator& it) { _it = it._it; } ~Iterator() { } Iterator& operator = (const Iterator& it) { _it = it._it; return *this; } inline bool operator == (const Iterator& it) const { return _it == it._it; } inline bool operator != (const Iterator& it) const { return _it != it._it; } Iterator& operator ++ () // prefix { ++_it; return *this; } Iterator operator ++ (int) // postfix { Iterator result(_it); ++_it; return result; } inline const Pair* operator * () const { _pair.first = _it->first; _pair.second = _it->second.pManifest; return &_pair; } inline const Pair* operator -> () const { _pair.first = _it->first; _pair.second = _it->second.pManifest; return &_pair; } private: typename LibraryMap::const_iterator _it; mutable Pair _pair; }; ClassLoader() /// Creates the ClassLoader. { } virtual ~ClassLoader() /// Destroys the ClassLoader. { for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it) { delete it->second.pLibrary; delete it->second.pManifest; } } void loadLibrary(const std::string& path) /// Loads a library from the given path. Does nothing /// if the library is already loaded. /// Throws a LibraryLoadException if the library /// cannot be loaded or does not have a Manifest. /// If the library exports a function named "pocoInitializeLibrary", /// this function is executed. /// If called multiple times for the same library, /// the number of calls to unloadLibrary() must be the same /// for the library to become unloaded. { FastMutex::ScopedLock lock(_mutex); typename LibraryMap::iterator it = _map.find(path); if (it == _map.end()) { LibraryInfo li; li.pLibrary = new SharedLibrary(path); li.pManifest = new Manif(); li.refCount = 1; try { if (li.pLibrary->hasSymbol("pocoInitializeLibrary")) { InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) li.pLibrary->getSymbol("pocoInitializeLibrary"); initializeLibrary(); } if (li.pLibrary->hasSymbol("pocoBuildManifest")) { BuildManifestFunc buildManifest = (BuildManifestFunc) li.pLibrary->getSymbol("pocoBuildManifest"); if (buildManifest(const_cast<Manif*>(li.pManifest))) _map[path] = li; else throw LibraryLoadException(std::string("Manifest class mismatch in ") + path); } else throw LibraryLoadException(std::string("No manifest in ") + path); } catch (...) { delete li.pLibrary; delete li.pManifest; throw; } } else { ++it->second.refCount; } } void unloadLibrary(const std::string& path) /// Unloads the given library. /// Be extremely cautious when unloading shared libraries. /// If objects from the library are still referenced somewhere, /// a total crash is very likely. /// If the library exports a function named "pocoUninitializeLibrary", /// this function is executed before it is unloaded. /// If loadLibrary() has been called multiple times for the same /// library, the number of calls to unloadLibrary() must be the same /// for the library to become unloaded. { FastMutex::ScopedLock lock(_mutex); typename LibraryMap::iterator it = _map.find(path); if (it != _map.end()) { if (--it->second.refCount == 0) { if (it->second.pLibrary->hasSymbol("pocoUninitializeLibrary")) { UninitializeLibraryFunc uninitializeLibrary = (UninitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoUninitializeLibrary"); uninitializeLibrary(); } delete it->second.pManifest; it->second.pLibrary->unload(); delete it->second.pLibrary; _map.erase(it); } } else throw NotFoundException(path); } const Meta* findClass(const std::string& className) const /// Returns a pointer to the MetaObject for the given /// class, or a null pointer if the class is not known. { FastMutex::ScopedLock lock(_mutex); for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it) { const Manif* pManif = it->second.pManifest; typename Manif::Iterator itm = pManif->find(className); if (itm != pManif->end()) return *itm; } return 0; } const Meta& classFor(const std::string& className) const /// Returns a reference to the MetaObject for the given /// class. Throws a NotFoundException if the class /// is not known. { const Meta* pMeta = findClass(className); if (pMeta) return *pMeta; else throw NotFoundException(className); } Base* create(const std::string& className) const /// Creates an instance of the given class. /// Throws a NotFoundException if the class /// is not known. { return classFor(className).create(); } Base& instance(const std::string& className) const /// Returns a reference to the sole instance of /// the given class. The class must be a singleton, /// otherwise an InvalidAccessException will be thrown. /// Throws a NotFoundException if the class /// is not known. { return classFor(className).instance(); } bool canCreate(const std::string& className) const /// Returns true if create() can create new instances /// of the class. { return classFor(className).canCreate(); } void destroy(const std::string& className, Base* pObject) const /// Destroys the object pObject points to. /// Does nothing if object is not found. { classFor(className).destroy(pObject); } bool isAutoDelete(const std::string& className, Base* pObject) const /// Returns true if the object is automatically /// deleted by its meta object. { return classFor(className).isAutoDelete(pObject); } const Manif* findManifest(const std::string& path) const /// Returns a pointer to the Manifest for the given /// library, or a null pointer if the library has not been loaded. { FastMutex::ScopedLock lock(_mutex); typename LibraryMap::const_iterator it = _map.find(path); if (it != _map.end()) return it->second.pManifest; else return 0; } const Manif& manifestFor(const std::string& path) const /// Returns a reference to the Manifest for the given library /// Throws a NotFoundException if the library has not been loaded. { const Manif* pManif = findManifest(path); if (pManif) return *pManif; else throw NotFoundException(path); } bool isLibraryLoaded(const std::string& path) const /// Returns true if the library with the given name /// has already been loaded. { return findManifest(path) != 0; } Iterator begin() const { FastMutex::ScopedLock lock(_mutex); return Iterator(_map.begin()); } Iterator end() const { FastMutex::ScopedLock lock(_mutex); return Iterator(_map.end()); }private: LibraryMap _map; mutable FastMutex _mutex;};} // namespace Poco#endif // Foundation_ClassLoader_INCLUDED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -