00001 00031 #ifndef LL_MEMORY_H 00032 #define LL_MEMORY_H 00033 00034 #include <new> 00035 #include <cstdlib> 00036 00037 #include "llerror.h" 00038 00039 extern S32 gTotalDAlloc; 00040 extern S32 gTotalDAUse; 00041 extern S32 gDACount; 00042 00043 const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA; 00044 00045 //---------------------------------------------------------------------------- 00046 00047 class LLMemory 00048 { 00049 public: 00050 static void initClass(); 00051 static void cleanupClass(); 00052 static void freeReserve(); 00053 private: 00054 static char* reserveMem; 00055 }; 00056 00057 //---------------------------------------------------------------------------- 00058 // RefCount objects should generally only be accessed by way of LLPointer<>'s 00059 // NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE 00060 // if LLFoo::LLFoo() does anything like put itself in an update queue. 00061 // The queue may get accessed before it gets assigned to x. 00062 // The correct implementation is: 00063 // LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting 00064 // x->instantiate(); // does stuff like place x into an update queue 00065 00066 // see llthread.h for LLThreadSafeRefCount 00067 00068 //---------------------------------------------------------------------------- 00069 00070 class LLRefCount 00071 { 00072 protected: 00073 LLRefCount(const LLRefCount&); // not implemented 00074 private: 00075 LLRefCount&operator=(const LLRefCount&); // not implemented 00076 00077 protected: 00078 virtual ~LLRefCount(); // use unref() 00079 00080 public: 00081 LLRefCount(); 00082 00083 void ref() 00084 { 00085 mRef++; 00086 } 00087 00088 S32 unref() 00089 { 00090 llassert(mRef >= 1); 00091 if (0 == --mRef) 00092 { 00093 delete this; 00094 return 0; 00095 } 00096 return mRef; 00097 } 00098 00099 S32 getNumRefs() const 00100 { 00101 return mRef; 00102 } 00103 00104 private: 00105 S32 mRef; 00106 }; 00107 00108 //---------------------------------------------------------------------------- 00109 00110 // Note: relies on Type having ref() and unref() methods 00111 template <class Type> class LLPointer 00112 { 00113 public: 00114 00115 LLPointer() : 00116 mPointer(NULL) 00117 { 00118 } 00119 00120 LLPointer(Type* ptr) : 00121 mPointer(ptr) 00122 { 00123 ref(); 00124 } 00125 00126 LLPointer(const LLPointer<Type>& ptr) : 00127 mPointer(ptr.mPointer) 00128 { 00129 ref(); 00130 } 00131 00132 // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. 00133 template<typename Subclass> 00134 LLPointer(const LLPointer<Subclass>& ptr) : 00135 mPointer(ptr.get()) 00136 { 00137 ref(); 00138 } 00139 00140 ~LLPointer() 00141 { 00142 unref(); 00143 } 00144 00145 Type* get() const { return mPointer; } 00146 const Type* operator->() const { return mPointer; } 00147 Type* operator->() { return mPointer; } 00148 const Type& operator*() const { return *mPointer; } 00149 Type& operator*() { return *mPointer; } 00150 00151 operator BOOL() const { return (mPointer != NULL); } 00152 operator bool() const { return (mPointer != NULL); } 00153 bool operator!() const { return (mPointer == NULL); } 00154 bool isNull() const { return (mPointer == NULL); } 00155 bool notNull() const { return (mPointer != NULL); } 00156 00157 operator Type*() const { return mPointer; } 00158 operator const Type*() const { return mPointer; } 00159 bool operator !=(Type* ptr) const { return (mPointer != ptr); } 00160 bool operator ==(Type* ptr) const { return (mPointer == ptr); } 00161 bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } 00162 bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } 00163 bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } 00164 00165 LLPointer<Type>& operator =(Type* ptr) 00166 { 00167 if( mPointer != ptr ) 00168 { 00169 unref(); 00170 mPointer = ptr; 00171 ref(); 00172 } 00173 00174 return *this; 00175 } 00176 00177 LLPointer<Type>& operator =(const LLPointer<Type>& ptr) 00178 { 00179 if( mPointer != ptr.mPointer ) 00180 { 00181 unref(); 00182 mPointer = ptr.mPointer; 00183 ref(); 00184 } 00185 return *this; 00186 } 00187 00188 // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. 00189 template<typename Subclass> 00190 LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) 00191 { 00192 if( mPointer != ptr.get() ) 00193 { 00194 unref(); 00195 mPointer = ptr.get(); 00196 ref(); 00197 } 00198 return *this; 00199 } 00200 00201 // Just exchange the pointers, which will not change the reference counts. 00202 static void swap(LLPointer<Type>& a, LLPointer<Type>& b) 00203 { 00204 Type* temp = a.mPointer; 00205 a.mPointer = b.mPointer; 00206 b.mPointer = temp; 00207 } 00208 00209 protected: 00210 void ref() 00211 { 00212 if (mPointer) 00213 { 00214 mPointer->ref(); 00215 } 00216 } 00217 00218 void unref() 00219 { 00220 if (mPointer) 00221 { 00222 Type *tempp = mPointer; 00223 mPointer = NULL; 00224 tempp->unref(); 00225 if (mPointer != NULL) 00226 { 00227 llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; 00228 unref(); 00229 } 00230 } 00231 } 00232 00233 protected: 00234 Type* mPointer; 00235 }; 00236 00237 //template <class Type> 00238 //class LLPointerTraits 00239 //{ 00240 // static Type* null(); 00241 //}; 00242 // 00243 // Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. 00244 // This is useful in instances where operations on NULL pointers are semantically safe and/or 00245 // when error checking occurs at a different granularity or in a different part of the code 00246 // than when referencing an object via a LLHandle. 00247 // 00248 00249 template <class Type> 00250 class LLHandle 00251 { 00252 public: 00253 LLHandle() : 00254 mPointer(NULL) 00255 { 00256 } 00257 00258 LLHandle(Type* ptr) : 00259 mPointer(NULL) 00260 { 00261 assign(ptr); 00262 } 00263 00264 LLHandle(const LLHandle<Type>& ptr) : 00265 mPointer(NULL) 00266 { 00267 assign(ptr.mPointer); 00268 } 00269 00270 // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. 00271 template<typename Subclass> 00272 LLHandle(const LLHandle<Subclass>& ptr) : 00273 mPointer(NULL) 00274 { 00275 assign(ptr.get()); 00276 } 00277 00278 ~LLHandle() 00279 { 00280 unref(); 00281 } 00282 00283 const Type* operator->() const { return nonNull(mPointer); } 00284 Type* operator->() { return nonNull(mPointer); } 00285 00286 Type* get() const { return mPointer; } 00287 // we disallow these operations as they expose our null objects to direct manipulation 00288 // and bypass the reference counting semantics 00289 //const Type& operator*() const { return *nonNull(mPointer); } 00290 //Type& operator*() { return *nonNull(mPointer); } 00291 00292 operator BOOL() const { return mPointer != NULL; } 00293 operator bool() const { return mPointer != NULL; } 00294 bool operator!() const { return mPointer == NULL; } 00295 bool isNull() const { return mPointer == NULL; } 00296 bool notNull() const { return mPointer != NULL; } 00297 00298 00299 operator Type*() const { return mPointer; } 00300 operator const Type*() const { return mPointer; } 00301 bool operator !=(Type* ptr) const { return (mPointer != ptr); } 00302 bool operator ==(Type* ptr) const { return (mPointer == ptr); } 00303 bool operator ==(const LLHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); } 00304 bool operator < (const LLHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); } 00305 bool operator > (const LLHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); } 00306 00307 LLHandle<Type>& operator =(Type* ptr) 00308 { 00309 assign(ptr); 00310 return *this; 00311 } 00312 00313 LLHandle<Type>& operator =(const LLHandle<Type>& ptr) 00314 { 00315 assign(ptr.mPointer); 00316 return *this; 00317 } 00318 00319 // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. 00320 template<typename Subclass> 00321 LLHandle<Type>& operator =(const LLHandle<Subclass>& ptr) 00322 { 00323 assign(ptr.get()); 00324 return *this; 00325 } 00326 00327 public: 00328 typedef Type* (*NullFunc)(); 00329 static const NullFunc sNullFunc; 00330 00331 protected: 00332 void ref() 00333 { 00334 if (mPointer) 00335 { 00336 mPointer->ref(); 00337 } 00338 } 00339 00340 void unref() 00341 { 00342 if (mPointer) 00343 { 00344 Type *tempp = mPointer; 00345 mPointer = NULL; 00346 tempp->unref(); 00347 if (mPointer != NULL) 00348 { 00349 llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; 00350 unref(); 00351 } 00352 } 00353 } 00354 00355 void assign(Type* ptr) 00356 { 00357 if( mPointer != ptr ) 00358 { 00359 unref(); 00360 mPointer = ptr; 00361 ref(); 00362 } 00363 } 00364 00365 static Type* nonNull(Type* ptr) 00366 { 00367 return ptr == NULL ? sNullFunc() : ptr; 00368 } 00369 00370 protected: 00371 Type* mPointer; 00372 }; 00373 00374 // LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL 00375 // NOT a smart pointer like LLPointer<> 00376 // Useful for example in std::map<int,LLInitializedPointer<LLFoo> > 00377 // (std::map uses the default constructor for creating new entries) 00378 template <typename T> class LLInitializedPointer 00379 { 00380 public: 00381 LLInitializedPointer() : mPointer(NULL) {} 00382 ~LLInitializedPointer() { delete mPointer; } 00383 00384 const T* operator->() const { return mPointer; } 00385 T* operator->() { return mPointer; } 00386 const T& operator*() const { return *mPointer; } 00387 T& operator*() { return *mPointer; } 00388 operator const T*() const { return mPointer; } 00389 operator T*() { return mPointer; } 00390 T* operator=(T* x) { return (mPointer = x); } 00391 operator bool() const { return mPointer != NULL; } 00392 bool operator!() const { return mPointer == NULL; } 00393 bool operator==(T* rhs) { return mPointer == rhs; } 00394 bool operator==(const LLInitializedPointer<T>* rhs) { return mPointer == rhs.mPointer; } 00395 00396 protected: 00397 T* mPointer; 00398 }; 00399 00400 //---------------------------------------------------------------------------- 00401 00402 // LLSingleton implements the getInstance() method part of the Singleton pattern. It can't make 00403 // the derived class constructors protected, though, so you have to do that yourself. 00404 // The proper way to use LLSingleton is to inherit from it while using the typename that you'd 00405 // like to be static as the template parameter, like so: 00406 // class FooBar: public LLSingleton<FooBar> 00407 // As currently written, it is not thread-safe. 00408 template <typename T> 00409 class LLSingleton 00410 { 00411 public: 00412 static T* getInstance() 00413 { 00414 static T instance; 00415 return &instance; 00416 } 00417 }; 00418 00419 //---------------------------------------------------------------------------- 00420 00421 // Return the resident set size of the current process, in bytes. 00422 // Return value is zero if not known. 00423 U64 getCurrentRSS(); 00424 00425 #endif