PixelLightAPI  .
ClassManager.h
Go to the documentation of this file.
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__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:08:52
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported