ResourceHolder.h

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 #ifndef _NR_RESOURCE_HOLDER_H_
00015 #define _NR_RESOURCE_HOLDER_H_
00016 
00017 
00018 //----------------------------------------------------------------------------------
00019 // Includes
00020 //----------------------------------------------------------------------------------
00021 #include "Prerequisities.h"
00022 
00023 namespace nrEngine{
00024         
00025         /**
00026         * This constant defines the size of the lock stack. 
00027         * All locking states are stored in the stack, to allow nested lock/unlock calling.
00028         * \ingroup resource
00029         **/
00030         const int32 NR_RESOURCE_LOCK_STACK = 128;
00031 
00032         //! Interstage between manager and resources for more efficience and safety
00033         /**
00034         * This is a holder class which is holding a resource of different type.
00035         * Resource pointers are pointing to this holder, so by referencing the pointer
00036         * you do not have to ask the manager to get the resource, but directly to access
00037         * it through this holder. So actually resource manager manages holders and
00038         * not resources or pointers directly.
00039         *
00040         * We use such a system to be more efficient by dereferncing the resource pointer.
00041         * Other and more trivial way is to ask the manager for resource by giving him the
00042         * handle. This end in a look up of handle tables and returning the resource pointer.
00043         * If we use holders, pointers will directly access that holders and each holder
00044         * is showing to one resource. So we do not have to do any lookups.
00045         *
00046         * This class is working transparent to the whole resource management system, so
00047         * you actually do not have to know how this class works and you also do not have
00048         * to derive any classes from it.
00049         *
00050         * This system was get from Game Programming Gems 4, and was expanded to be more
00051         * flexible and more efficient.
00052         *
00053         * \ingroup resource
00054         */
00055         class _NRExport ResourceHolder{
00056                 public:
00057                                         
00058                         /**
00059                         * Remove the object from the memory and also delete the resource
00060                         * which is holded by this holder. The destructor should be declared as
00061                         * public so it can be used by smart pointers
00062                         **/
00063                         ~ResourceHolder();
00064 
00065                 private:
00066 
00067                         friend class IResourceLoader;
00068                         friend class IResourcePtr;
00069                         friend class ResourceManager;
00070                         
00071                         /**
00072                         * Create the object of this class
00073                         **/
00074                         ResourceHolder(IResource* res, IResource* empty);
00075                 
00076                         //! pointer that holds the resource
00077                         IResource* mResource;
00078                         
00079                         //! pointer that holds the empty resource object
00080                         IResource* mEmptyResource;
00081                         
00082                         //! Store number that represents how often the resource was in use
00083                         uint32          countAccess;
00084                         
00085                         //! Store the status if real resources lock stack
00086                         bool            mLockStack[NR_RESOURCE_LOCK_STACK];
00087                         
00088                         //! Current position in the stack
00089                         int32           mLockStackTop;
00090                         
00091                         //! Empty lock status
00092                         bool mEmptyLockStack[NR_RESOURCE_LOCK_STACK];
00093                         
00094                         //! Position in empty locking state 
00095                         int32 mEmptyLockStackTop;
00096                         
00097                         /**
00098                         * Lock real resource for using. Locking has the effect that the getResource() method
00099                         * will now return real resources also if it is unloaded.
00100                         *
00101                         * @return true if locking was successfull otherwise false
00102                         * @note If the lock stack is full you are not able lock anymore
00103                         **/
00104                         bool lockResource();
00105                         
00106                         /**
00107                         * Unlock the real resurce. After unlocking you have standard behavior about using
00108                         * of empty resources. If resource is unloaded, so empty resource will be used.
00109                         *
00110                         * @return true if unlocking was successfull otherwise false
00111                         * @note In complement of the locking, you are always able to unlock. 
00112                         *               If the lock state stack is empty and you are unlocking the resource, so this
00113                         *               do not affect anything.
00114                         **/
00115                         void unlockResource();
00116                         
00117                         /**
00118                          * Lock an empty resource to be used even if a real resource is loaded.
00119                          * This method can be used to temporary point all pointers to 
00120                          * an empty resource instead of a real one.
00121                          *
00122                          * If you lock an empty and pure/real resource at the same time,
00123                          * so warning will be generated and an empty resource will be given
00124                          * @see lockPure();
00125                          **/
00126                         bool lockEmpty();
00127                         
00128                         /**
00129                         * Unlock from an empty resource and switch to the case before the lock was done
00130                         **/
00131                         void unlockEmpty();
00132                         
00133                         /**
00134                         * Reset the stored resource to a new value
00135                         **/
00136                         void resetResource(IResource* res);
00137                 
00138                         /**
00139                         * Returns true if this holder has a pointer to a empty resource
00140                         **/
00141                         NR_FORCEINLINE bool hasEmpty() const{
00142                                 return mEmptyResource == NULL;
00143                         }
00144                 
00145                         /**
00146                         * Return the number of access to this resource
00147                         **/
00148                         NR_FORCEINLINE uint32 getAccessCount() const{
00149                                 return countAccess;
00150                         }
00151                         
00152                         /**
00153                         * Each access to the resource will should call this function. Here 
00154                         * we do work that has to be done if a resource was used.
00155                         **/
00156                         void touchResource();
00157                         
00158                         /**
00159                         * Check whenever the resource is currently locked
00160                         **/
00161                         NR_FORCEINLINE bool isLocked(){
00162                                 if (mLockStackTop > 0) 
00163                                         return mLockStack[mLockStackTop - 1];
00164                                 else
00165                                         return false;
00166                         }
00167                         
00168                         /**
00169                         * Check whenever the resource is currently locked to an empty resource
00170                         **/
00171                         NR_FORCEINLINE bool isEmptyLocked()
00172                         {
00173                                 if (mEmptyLockStackTop > 0) 
00174                                         return mEmptyLockStack[mEmptyLockStackTop - 1];
00175                                 else
00176                                         return false;
00177                         }
00178                         
00179                         /**
00180                         * This will bind this holder to specific empty resource.
00181                         * After loading of a resource from a file the manager will
00182                         * create/load the empty resource according to the type of the resource.
00183                         * Then it will generate a name for it and will bind the holder to that
00184                         * empty resource. So if you will next load a resource of the same type,
00185                         * so holder's empty resource pointer will still point to the same one.
00186                         **/
00187                         void setEmptyResource(IResource* res);
00188                         //void setEmptyResource(SharedPtr<IResource> res);
00189                 
00190                         /**
00191                         * Returns the empty resource of the resource type holded by this holder.
00192                         **/
00193                         IResource* getEmpty();
00194                 
00195                         
00196                         /**
00197                         * Get access to the stored resource.
00198                         * We declare this function as private, so we cannot access to the resource
00199                         * from outside either as from manager or a smart pointer to resources.
00200                         * We need to do it in such a way, to prevent you from deleting the resources
00201                         * from outside as from the resource management system.
00202                         *
00203                         * If the resource is temporary unloaded or if it is not exists, the holder will
00204                         * give you the empty resource back, which still can be NULL or not
00205                         *
00206                         * Each call of getResource() method will count up the access number.
00207                         **/
00208                         IResource* getResource();
00209                                 
00210         };
00211 
00212 };
00213 #endif

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1