PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: ClassManager.h * 00003 * 00004 * Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLCORE_CLASSMANAGER_H__ 00024 #define __PLCORE_CLASSMANAGER_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include "PLCore/PLCoreDefinitions.h" 00032 #include "PLCore/Core/Singleton.h" 00033 #include "PLCore/Container/List.h" 00034 #include "PLCore/Container/HashMap.h" 00035 #include "PLCore/Base/Event/Event.h" 00036 00037 00038 //[-------------------------------------------------------] 00039 //[ Namespace ] 00040 //[-------------------------------------------------------] 00041 namespace PLCore { 00042 00043 00044 //[-------------------------------------------------------] 00045 //[ Forward declarations ] 00046 //[-------------------------------------------------------] 00047 class Url; 00048 class Class; 00049 class Module; 00050 class ClassImpl; 00051 template <typename T> class ModuleID; 00052 00053 00054 //[-------------------------------------------------------] 00055 //[ Classes ] 00056 //[-------------------------------------------------------] 00057 /** 00058 * @brief 00059 * Manager providing access to RTTI classes 00060 */ 00061 class ClassManager : public Singleton<ClassManager> { 00062 00063 00064 //[-------------------------------------------------------] 00065 //[ Friends ] 00066 //[-------------------------------------------------------] 00067 friend class Singleton<ClassManager>; 00068 friend class ModuleID<int>; 00069 friend class ClassReal; 00070 friend class ClassDummy; 00071 00072 00073 //[-------------------------------------------------------] 00074 //[ Public events ] 00075 //[-------------------------------------------------------] 00076 public: 00077 Event<const Module*> EventModuleLoaded; /**< A module has been registered (do not destroy the given instance) */ 00078 Event<const Module*> EventModuleUnloaded; /**< A module has been removed (do not destroy the given instance) */ 00079 Event<const Class*> EventClassLoaded; /**< A class has been registered. Please note: At the time you receive this event, the class may not yet be fully initialized, this means that even "IsDerivedFrom" may not work, yet. (do not destroy the given instance) */ 00080 Event<const Class*> EventClassUnloaded; /**< A class has been removed (do not destroy the given instance) */ 00081 00082 00083 //[-------------------------------------------------------] 00084 //[ Public static PLCore::Singleton functions ] 00085 //[-------------------------------------------------------] 00086 // This solution enhances the compatibility with legacy compilers like GCC 4.2.1 used on Mac OS X 10.6 00087 // -> The C++11 feature "extern template" (C++11, see e.g. http://www2.research.att.com/~bs/C++0xFAQ.html#extern-templates) can only be used on modern compilers like GCC 4.6 00088 // -> We can't break legacy compiler support, especially when only the singletons are responsible for the break 00089 // -> See PLCore::Singleton for more details about singletons 00090 public: 00091 static PLCORE_API ClassManager *GetInstance(); 00092 static PLCORE_API bool HasInstance(); 00093 00094 00095 //[-------------------------------------------------------] 00096 //[ Public functions ] 00097 //[-------------------------------------------------------] 00098 public: 00099 /** 00100 * @brief 00101 * Get all registered modules 00102 * 00103 * @return 00104 * List of modules (do not destroy the returned instances) 00105 */ 00106 inline const List<const Module*> &GetModules() const; 00107 00108 /** 00109 * @brief 00110 * Get module by ID 00111 * 00112 * @param[in] nModuleID 00113 * Module ID 00114 * 00115 * @return 00116 * Pointer to module (do not destroy the returned instance, can be a null pointer) 00117 */ 00118 inline const Module *GetModuleByID(uint32 nModuleID) const; 00119 00120 /** 00121 * @brief 00122 * Get module by name 00123 * 00124 * @param[in] sModuleName 00125 * Module name 00126 * 00127 * @return 00128 * Pointer to module (do not destroy the returned instance, can be a null pointer) 00129 * 00130 * @note 00131 * - Whenever possible use "GetModuleByID()" instead of "GetModuleByName()" because 00132 * unlike the module name, the module ID is guaranteed do be unique 00133 */ 00134 PLCORE_API const Module *GetModuleByName(const String &sModuleName) const; 00135 00136 /** 00137 * @brief 00138 * Load a module 00139 * 00140 * @param[in] sAbsFilename 00141 * Absolute filename of the shared library to load in 00142 * @param[in] bForceBuildTypeMatch 00143 * 'true' to force a build type match, else 'false' 00144 * 00145 * @return 00146 * The loaded module, null pointer on error (do not destroy the returned instance) 00147 * 00148 * @note 00149 * - If the module was already loaded, this module instance is returned instead 00150 */ 00151 PLCORE_API const Module *LoadModule(const String &sAbsFilename, bool bForceBuildTypeMatch = false); 00152 00153 /** 00154 * @brief 00155 * Scan a directory for compatible plugins and load them in 00156 * 00157 * @param[in] sPath 00158 * Directory to search in 00159 * @param[in] nRecursive 00160 * Also take sub-directories into account? 00161 * @param[in] bDelayedPluginLoading 00162 * 'true' if it's allowed to perform delayed shared library loading to speed up the program start, else 'false' 00163 * 00164 * @return 00165 * 'true' if all went fine, else 'false' 00166 * 00167 * @remarks 00168 * This function scans for '.plugin'-files and registers the plugins if all went fine. 00169 */ 00170 PLCORE_API bool ScanPlugins(const String &sPath, ERecursive nRecursive = Recursive, bool bDelayedPluginLoading = true); 00171 00172 /** 00173 * @brief 00174 * Load plugin 00175 * 00176 * @param[in] sFilename 00177 * Filename of the plugin (must be a '.plugin'-file!) 00178 * @param[in] bDelayedPluginLoading 00179 * 'true' if it's allowed to perform delayed shared library loading to speed up the program start, else 'false' 00180 * 00181 * @return 00182 * 'true' if all went fine, else 'false' 00183 */ 00184 PLCORE_API bool LoadPlugin(const String &sFilename, bool bDelayedPluginLoading = true); 00185 00186 /** 00187 * @brief 00188 * Unload plugin 00189 * 00190 * @param[in] pModule 00191 * Module to unload (must be valid!) 00192 * 00193 * @return 00194 * 'true' if all went fine, else 'false' (maybe the module is static) 00195 * 00196 * @note 00197 * - You can only unload plugins modules, other modules will be ignored 00198 */ 00199 PLCORE_API bool UnloadPlugin(Module *pModule); 00200 00201 /** 00202 * @brief 00203 * Unload all plugins 00204 * 00205 * @return 00206 * 'true' if all went fine, else 'false' 00207 */ 00208 PLCORE_API bool UnloadAllPlugins(); 00209 00210 /** 00211 * @brief 00212 * Get all registered classes 00213 * 00214 * @return 00215 * List of classes (do not destroy the returned instances) 00216 */ 00217 inline const List<const Class*> &GetClasses() const; 00218 00219 /** 00220 * @brief 00221 * Get classes based on their base class and/or module (search for classes) 00222 * 00223 * @param[out] lstClasses 00224 * List that receives the found classes (do not destroy the returned instances) 00225 * @param[in] sClass 00226 * Name of base class (with namespace) 00227 * @param[in] nRecursive 00228 * 'Recursive' to list all subclasses of the base class, 'NonRecursive' to only list direct subclasses 00229 * @param[in] nIncludeBase 00230 * 'IncludeBase' to include the base class itself, 'NoBase' to exclude it 00231 * @param[in] nIncludeAbstract 00232 * 'IncludeAbstract' to include classes without a constructor, 'NoAbstract' to exclude them 00233 * @param[in] nModuleID 00234 * ID of module, or 0 to include the classes from all modules 00235 * 00236 * @remarks 00237 * The found classes will be added to the list that is passed as the first argument to the function. 00238 * The class list is not automatically cleared by this function. 00239 */ 00240 PLCORE_API void GetClasses(List<const Class*> &lstClasses, const String &sClass, ERecursive nRecursive = Recursive, EIncludeBase nIncludeBase = IncludeBase, EIncludeAbstract nIncludeAbstract = IncludeAbstract, uint32 nModuleID = 0) const; 00241 00242 /** 00243 * @brief 00244 * Get class 00245 * 00246 * @param[in] sClass 00247 * Class name 00248 * 00249 * @return 00250 * Pointer to the class, or a null pointer on error (do not destroy the returned instance) 00251 */ 00252 inline const Class *GetClass(const String &sClass) const; 00253 00254 00255 //[-------------------------------------------------------] 00256 //[ Private functions ] 00257 //[-------------------------------------------------------] 00258 private: 00259 /** 00260 * @brief 00261 * Constructor 00262 */ 00263 PLCORE_API ClassManager(); 00264 00265 /** 00266 * @brief 00267 * Copy constructor 00268 * 00269 * @param[in] cSource 00270 * Source to copy from 00271 */ 00272 PLCORE_API ClassManager(const ClassManager &cSource); 00273 00274 /** 00275 * @brief 00276 * Destructor 00277 */ 00278 PLCORE_API virtual ~ClassManager(); 00279 00280 /** 00281 * @brief 00282 * Copy operator 00283 * 00284 * @param[in] cSource 00285 * Source to copy from 00286 * 00287 * @return 00288 * Reference to this instance 00289 */ 00290 PLCORE_API ClassManager &operator =(const ClassManager &cSource); 00291 00292 /** 00293 * @brief 00294 * Get a unique module ID 00295 * 00296 * @return 00297 * Unique module ID for a new module 00298 */ 00299 PLCORE_API uint32 GetUniqueModuleID(); 00300 00301 /** 00302 * @brief 00303 * Create module 00304 * 00305 * @param[in] nModuleID 00306 * Module ID 00307 * 00308 * @return 00309 * Module belonging to that ID 00310 * 00311 * @remarks 00312 * If a module with that ID already exists, the function will return a pointer to it. 00313 * Otherwise it will create a new module and assign it to the given ID. 00314 */ 00315 PLCORE_API Module *CreateModule(uint32 nModuleID); 00316 00317 /** 00318 * @brief 00319 * Load a module delayed 00320 * 00321 * @param[in] cPluginElement 00322 * The XML element we're loading from 00323 * @param[in] sAbsFilename 00324 * Absolute filename of the shared library to load in 00325 * @param[in] bForceBuildTypeMatch 00326 * 'true' to force a build type match, else 'false' 00327 */ 00328 PLCORE_API void LoadModuleDelayed(const XmlElement &cPluginElement, const String &sAbsFilename, bool bForceBuildTypeMatch = false); 00329 00330 /** 00331 * @brief 00332 * Register module 00333 * 00334 * @param[in] pnModuleID 00335 * Pointer to a static module ID variable inside the shared library or executable the module is implemented in, always valid ("memory anchor") 00336 * @param[in] sName 00337 * Module name 00338 * @param[in] sVendor 00339 * Vendor name 00340 * @param[in] sLicense 00341 * Module license 00342 * @param[in] sDescription 00343 * Module description 00344 */ 00345 PLCORE_API void RegisterModule(const uint32 *pnModuleID, const String &sName, const String &sVendor, const String &sLicense, const String &sDescription); 00346 00347 /** 00348 * @brief 00349 * Unregister module 00350 * 00351 * @param[in] pModule 00352 * Module (must be valid!) 00353 */ 00354 PLCORE_API void UnregisterModule(Module *pModule); 00355 00356 /** 00357 * @brief 00358 * Register class 00359 * 00360 * @param[in] nModuleID 00361 * Module ID 00362 * @param[in] pClassImpl 00363 * Pointer to class implementation (must be valid), if it's a dummy the 00364 * class manager takes over the control and will destroy it if it's no longer needed 00365 * 00366 * @note 00367 * - Called automatically by the RTTI system (see "pl_class"-macro) 00368 */ 00369 PLCORE_API void RegisterClass(uint32 nModuleID, ClassImpl *pClassImpl); 00370 00371 /** 00372 * @brief 00373 * Unregister class 00374 * 00375 * @param[in] nModuleID 00376 * Module ID 00377 * @param[in] pClassImpl 00378 * Pointer to class implementation (must be valid), if it's a dummy the 00379 * class manager takes over the control and will destroy it if it's no longer needed 00380 * 00381 * @note 00382 * - Called automatically by the RTTI system (see "pl_class"-macro) 00383 */ 00384 PLCORE_API void UnregisterClass(uint32 nModuleID, ClassImpl *pClassImpl); 00385 00386 /** 00387 * @brief 00388 * Load file format version 1 plugin 00389 * 00390 * @param[in] cUrl 00391 * XML plugin file URL 00392 * @param[in] cPluginElement 00393 * XML plugin element with the plugin information 00394 * @param[in] bDelayedPluginLoading 00395 * 'true' if it's allowed to perform delayed shared library loading to speed up the program start, else 'false' 00396 * 00397 * @return 00398 * 'true' if all went fine, else 'false' 00399 */ 00400 PLCORE_API bool LoadPluginV1(const Url &cUrl, const XmlElement &cPluginElement, bool bDelayedPluginLoading = true); 00401 00402 00403 //[-------------------------------------------------------] 00404 //[ Private data ] 00405 //[-------------------------------------------------------] 00406 private: 00407 // Modules 00408 uint32 m_nModuleID; /**< Module ID counter */ 00409 List<const Module*> m_lstModules; /**< List of all modules */ 00410 HashMap<uint32, const Module*> m_mapModules; /**< Hash-map of module IDs to modules */ 00411 // Classes 00412 List<const Class*> m_lstClasses; /**< List of all classes */ 00413 HashMap<String, const Class*> m_mapClasses; /**< Hash-map of class names to classes (with namespace) */ 00414 00415 00416 }; 00417 00418 00419 //[-------------------------------------------------------] 00420 //[ Namespace ] 00421 //[-------------------------------------------------------] 00422 } // PLCore 00423 00424 00425 //[-------------------------------------------------------] 00426 //[ Implementation ] 00427 //[-------------------------------------------------------] 00428 #include "PLCore/Base/ClassManager.inl" 00429 00430 00431 #endif // __PLCORE_CLASSMANAGER_H__
|