/** * @file llmemory.h * @brief Memory allocation/deallocation header-stuff goes here. * * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. * $License$ */ #ifndef LL_MEMORY_H #define LL_MEMORY_H #include #include #include "llerror.h" #include "llthread.h" #include "llmemtype.h" extern S32 gTotalDAlloc; extern S32 gTotalDAUse; extern S32 gDACount; const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA; //---------------------------------------------------------------------------- class LLMemory { public: static void initClass(); static void cleanupClass(); static void freeReserve(); private: static char* reserveMem; }; //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s // NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE // if LLFoo::LLFoo() does anything like put itself in an update queue. // The queue may get accessed before it gets assigned to x. // The correct implementation is: // LLPointer x = new LLFoo; // constructor does not do anything interesting // x->instantiate(); // does stuff like place x into an update queue class LLThreadSafeRefCount { public: static void initClass(); // creates sMutex static void cleanupClass(); // destroys sMutex private: static LLMutex* sMutex; private: LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented protected: virtual ~LLThreadSafeRefCount(); // use unref() public: LLThreadSafeRefCount(); void ref() { if (sMutex) sMutex->lock(); mRef++; if (sMutex) sMutex->unlock(); } S32 unref() { llassert(mRef >= 1); if (sMutex) sMutex->lock(); S32 res = --mRef; if (sMutex) sMutex->unlock(); if (0 == res) { delete this; res = 0; } return res; } S32 getNumRefs() const { return mRef; } private: S32 mRef; }; //---------------------------------------------------------------------------- class LLRefCount { protected: LLRefCount(const LLRefCount&); // not implemented private: LLRefCount&operator=(const LLRefCount&); // not implemented protected: virtual ~LLRefCount(); // use unref() public: LLRefCount(); void ref() { mRef++; } S32 unref() { llassert(mRef >= 1); if (0 == --mRef) { delete this; return 0; } return mRef; } S32 getNumRefs() const { return mRef; } private: S32 mRef; }; //---------------------------------------------------------------------------- template class LLPointer { public: LLPointer() : mPointer(NULL) { } LLPointer(Type* ptr) : mPointer(ptr) { ref(); } LLPointer(const LLPointer& ptr) : mPointer(ptr.mPointer) { ref(); } // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template LLPointer(const LLPointer& ptr) : mPointer(ptr.get()) { ref(); } ~LLPointer() { unref(); } Type* get() const { return mPointer; } const Type* operator->() const { return mPointer; } Type* operator->() { return mPointer; } const Type& operator*() const { return *mPointer; } Type& operator*() { return *mPointer; } operator BOOL() const { return (mPointer != NULL); } operator bool() const { return (mPointer != NULL); } bool operator!() const { return (mPointer == NULL); } bool isNull() const { return (mPointer == NULL); } bool notNull() const { return (mPointer != NULL); } operator Type*() const { return mPointer; } operator const Type*() const { return mPointer; } bool operator !=(Type* ptr) const { return (mPointer != ptr); } bool operator ==(Type* ptr) const { return (mPointer == ptr); } bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } LLPointer& operator =(Type* ptr) { if( mPointer != ptr ) { unref(); mPointer = ptr; ref(); } return *this; } LLPointer& operator =(const LLPointer& ptr) { if( mPointer != ptr.mPointer ) { unref(); mPointer = ptr.mPointer; ref(); } return *this; } // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template LLPointer& operator =(const LLPointer& ptr) { if( mPointer != ptr.get() ) { unref(); mPointer = ptr.get(); ref(); } return *this; } protected: void ref() { if (mPointer) { mPointer->ref(); } } void unref() { if (mPointer) { Type *tempp = mPointer; mPointer = NULL; tempp->unref(); if (mPointer != NULL) { llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; unref(); } } } protected: Type* mPointer; }; // LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL // NOT a smart pointer like LLPointer<> // Useful for example in std::map > // (std::map uses the default constructor for creating new entries) template class LLInitializedPointer { public: LLInitializedPointer() : mPointer(NULL) {} ~LLInitializedPointer() { delete mPointer; } const T* operator->() const { return mPointer; } T* operator->() { return mPointer; } const T& operator*() const { return *mPointer; } T& operator*() { return *mPointer; } operator const T*() const { return mPointer; } operator T*() { return mPointer; } T* operator=(T* x) { return (mPointer = x); } operator bool() const { return mPointer != NULL; } bool operator!() const { return mPointer == NULL; } bool operator==(T* rhs) { return mPointer == rhs; } bool operator==(const LLInitializedPointer* rhs) { return mPointer == rhs.mPointer; } protected: T* mPointer; }; //---------------------------------------------------------------------------- // LLSingleton implements the getInstance() method part of the Singleton pattern. It can't make // the derived class constructors protected, though, so you have to do that yourself. // The proper way to use LLSingleton is to inherit from it while using the typename that you'd // like to be static as the template parameter, like so: // class FooBar: public LLSingleton // As currently written, it is not thread-safe. template class LLSingleton { public: static T* getInstance() { static T instance; return &instance; } }; //---------------------------------------------------------------------------- #endif