llmemory.h

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

Generated on Thu Jul 1 06:08:51 2010 for Second Life Viewer by  doxygen 1.4.7