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_POINTER_H_ 00015 #define _NR_RESOURCE_POINTER_H_ 00016 00017 00018 00019 //---------------------------------------------------------------------------------- 00020 // Includes 00021 //---------------------------------------------------------------------------------- 00022 #include "Prerequisities.h" 00023 #include "Exception.h" 00024 #include "Log.h" 00025 00026 namespace nrEngine{ 00027 00028 //! Base untemplated class for resource pointers 00029 /** 00030 * This is a base class for resource pointers. You can use this pointers as 00031 * normal pointers, except you can not use new,delete functions. 00032 * We need this base class which is not templated to implement converting 00033 * functions in derived classes 00034 * @note We do not have any public constructors or destructors. This will prevent 00035 * you by using the resource management system in the wrong way. You have 00036 * to use manager before you can use the pointers to resources. This will 00037 * give the nrEngine the safety of using its resource management system. 00038 * \ingroup resource 00039 **/ 00040 class _NRExport IResourcePtr{ 00041 public: 00042 00043 /** 00044 * Copy constructor 00045 **/ 00046 IResourcePtr(const IResourcePtr& resPtr); 00047 00048 /** 00049 * Create an empty resource pointer, that do not point to anywhere 00050 **/ 00051 IResourcePtr() 00052 { 00053 mHolder.reset(); 00054 } 00055 00056 /** 00057 * Virtual destructor 00058 **/ 00059 virtual ~IResourcePtr() 00060 { 00061 mHolder.reset(); 00062 }; 00063 00064 /** 00065 * Check if the given pointer is the same as this one. 00066 * @note Two pointers are the same, if they showing to the same resource, and 00067 * if their holders are the same or if 00068 * both pointers points to NULL. If one of the pointers is an empty pointer, 00069 * so also false will be returned. 00070 **/ 00071 virtual bool operator==(IResourcePtr& res) const; 00072 00073 00074 /** 00075 * Check equality to normal pointers. 00076 **/ 00077 virtual bool operator==(const IResource* p) const; 00078 00079 00080 /** 00081 * Check whenver two pointers are not the same. 00082 * @see operator== 00083 **/ 00084 virtual bool operator!=(IResourcePtr& res) const; 00085 00086 00087 /** 00088 * Check whenver two pointers are not the same. 00089 * @see operator== 00090 **/ 00091 virtual bool operator!=(const IResource* res) const; 00092 00093 00094 /** 00095 * Check whenever this pointer is NULL - does not contain data 00096 **/ 00097 NR_FORCEINLINE bool isNull()const { 00098 return (mHolder.get() == NULL); 00099 } 00100 00101 /** 00102 * Check whenever the pointer contains valid data. The method 00103 * if opossite to isNull() 00104 **/ 00105 NR_FORCEINLINE bool valid()const { 00106 return (mHolder.get() != NULL); 00107 } 00108 00109 /** 00110 * Lock the resource to which one this pointer points, to prevent using 00111 * of empty resource. See more information about locking of real resources 00112 * in the documentation about ResourceManager::lockPure() or 00113 * ResourceHolder::lockPure() 00114 * @return either OK or: 00115 * - RES_PTR_IS_NULL if this pointer is null 00116 * - RES_LOCK_STATE_STACK_IS_FULL if we are not able to lock anymore 00117 **/ 00118 Result lockResource(); 00119 00120 00121 /** 00122 * Unlock the resource to which one this pointer points, to prevent using 00123 * of empty resource. See more information about locking of real resources 00124 * in the documentation about ResourceManager::unlockpure() 00125 * @return either OK or RES_PTR_IS_NULL if this pointer is null 00126 **/ 00127 Result unlockResource(); 00128 00129 00130 /** 00131 * Lock an empty resource, so that even if resource is loaded, empty resource will 00132 * be used. 00133 * @see lockPure() 00134 **/ 00135 Result lockEmpty(); 00136 00137 /** 00138 * Unlock empty resource 00139 **/ 00140 Result unlockEmpty(); 00141 00142 /** 00143 * Access to the resource to which one this pointer points. This access need 00144 * 1 static_cast, 3 function calls until it returns the resource. 00145 * So this function is running in O(1) and is pretty efficient 00146 **/ 00147 IResource* getBase() const; 00148 00149 00150 /** 00151 * Access to the resource to which one this pointer points. This access need 00152 * 1 static_cast, 3 function calls until it returns the resource. 00153 * So this function is running in O(1) and is pretty efficient 00154 **/ 00155 //virtual IResource& operator*() const; 00156 00157 protected: 00158 00159 //! Resource Manager is a friend, so it can freely work with this pointers 00160 friend class IResourceLoader; 00161 00162 //! Also resource manager is a friend 00163 friend class ResourceManager; 00164 00165 //! Shared pointer holding the holder of the resource 00166 SharedPtr<ResourceHolder> mHolder; 00167 00168 /** 00169 * Get the holder to which one this pointer shows 00170 **/ 00171 NR_FORCEINLINE SharedPtr<ResourceHolder> getResourceHolder() const 00172 { 00173 return mHolder; 00174 } 00175 00176 /** 00177 * Create an instance of the resource pointer. This pointer is pointing 00178 * to the resource stored by the holder. The constructor is private, so you 00179 * can not use the new function to create the pointer. 00180 **/ 00181 IResourcePtr(SharedPtr<ResourceHolder> holder) 00182 { 00183 mHolder = holder; 00184 } 00185 00186 00187 }; 00188 00189 00190 00191 //! Resource pointer is a smart pointer pointing to the resource 00192 /** 00193 * This is a smart pointer that can be used to access resources manages by the 00194 * resource manager. This pointer will automaticly be pointing to empty resource 00195 * if the resource was unloaded by the manager. 00196 * 00197 * You can create more than one resource pointer to a resource. Each access to such 00198 * a resource through the manager will create a new one for you. However the pointers 00199 * are pointing to one resource holder. Each resource holder is controlled/managed 00200 * by the manager. So if you for example unload a resource to which one you has pointers, 00201 * the manager will replace the resource holding by the holder with empty one. So if 00202 * you try to access the resource you can still access them, but they are empty. 00203 * Our systems also allows you to delete the manager from the memory, but the pointers 00204 * will stay valid. So you can also remove the manager after you loaded all resources. 00205 * However you can then do not manage the resources, so this is a way you should <b>not</b> 00206 * do it !!! 00207 * 00208 * @note We do not have any public constructors or destructors. This will prevent 00209 * you by using the resource management system in the wrong way. You have 00210 * to use manager before you can use the pointers to resources. This will 00211 * give the nrEngine the safety of using its resource management system. 00212 * 00213 * \ingroup resource 00214 **/ 00215 template<typename ResType> 00216 class _NRExport ResourcePtr: public IResourcePtr{ 00217 public: 00218 00219 /** 00220 * Create an empty resource pointer. Such a pointer 00221 * does not point to anything. So using of not initialized 00222 * pointers will give you an exception 00223 **/ 00224 ResourcePtr() : IResourcePtr() {} 00225 00226 /** 00227 * Copy constructor to allow copying from base class 00228 **/ 00229 ResourcePtr(const IResourcePtr& res) : IResourcePtr(res){} 00230 00231 /** 00232 * Access to the resource to which one this pointer points. This access need 00233 * 1 static_cast, 3 function calls until it returns the resource. 00234 * So this function is running in O(1) and is pretty efficient 00235 **/ 00236 NR_FORCEINLINE ResType* operator->() const 00237 { 00238 ResType* ptr = dynamic_cast<ResType*>(IResourcePtr::getBase()); 00239 if (ptr == NULL) 00240 { 00241 NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourcePtr<%s> cannot cast from IResource", getBase()->getResourceName().c_str()); 00242 NR_ASSERT(ptr != NULL && "The resource has wrong type"); 00243 } 00244 return ptr; 00245 } 00246 00247 00248 /** 00249 * Get the object stored by this pointer. 00250 * NOTE: The instance is controlled by the pointer, so do not delete it 00251 **/ 00252 NR_FORCEINLINE ResType* get() 00253 { 00254 return operator->(); 00255 } 00256 00257 /** 00258 * Access to the resource to which one this pointer points. This access need 00259 * 1 static_cast, 3 function calls until it returns the resource. 00260 * So this function is running in O(1) and is pretty efficient 00261 **/ 00262 NR_FORCEINLINE ResType& operator*() const 00263 { 00264 return *(operator->()); 00265 } 00266 }; 00267 00268 }; 00269 #endif