diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llcommon/llmemory.h |
Print done when done.
Diffstat (limited to 'indra/llcommon/llmemory.h')
-rw-r--r-- | indra/llcommon/llmemory.h | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h new file mode 100644 index 0000000000..905d05254a --- /dev/null +++ b/indra/llcommon/llmemory.h @@ -0,0 +1,300 @@ +/** + * @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 <new> +#include <cstdlib> + +#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<LLFoo> 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<LLFoo> 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 Type> class LLPointer +{ +public: + + LLPointer() : + mPointer(NULL) + { + } + + LLPointer(Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLPointer(const LLPointer<Type>& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template<typename Subclass> + LLPointer(const LLPointer<Subclass>& 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<Type>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } + + LLPointer<Type>& operator =(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + + return *this; + } + + LLPointer<Type>& operator =(const LLPointer<Type>& 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<typename Subclass> + LLPointer<Type>& operator =(const LLPointer<Subclass>& 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<int,LLInitializedPointer<LLFoo> > +// (std::map uses the default constructor for creating new entries) +template <typename T> 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<T>* 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<FooBar> +// As currently written, it is not thread-safe. +template <typename T> +class LLSingleton +{ +public: + static T* getInstance() + { + static T instance; + return &instance; + } +}; + +//---------------------------------------------------------------------------- + +#endif + |