diff options
Diffstat (limited to 'indra/llcommon/llmemory.h')
-rw-r--r-- | indra/llcommon/llmemory.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 905d05254a..962a4aa5d5 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -120,6 +120,7 @@ public: } return mRef; } + S32 getNumRefs() const { return mRef; @@ -249,6 +250,154 @@ protected: Type* mPointer; }; +//template <class Type> +//class LLPointerTraits +//{ +// static Type* null(); +//}; +// +// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. +// This is useful in instances where operations on NULL pointers are semantically safe and/or +// when error checking occurs at a different granularity or in a different part of the code +// than when referencing an object via a LLHandle. +// + +template <class Type> +class LLHandle +{ +public: + LLHandle() : + mPointer(sNullFunc()) + { + ref(); + } + + LLHandle(Type* ptr) : + mPointer(nonNull(ptr)) + { + ref(); + } + + LLHandle(const LLHandle<Type>& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template<typename Subclass> + LLHandle(const LLPointer<Subclass>& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLHandle() + { + 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 != sNullFunc()); } + operator bool() const { return (mPointer != sNullFunc()); } + bool operator!() const { return (mPointer == sNullFunc()); } + bool isNull() const { return (mPointer == sNullFunc()); } + bool notNull() const { return (mPointer != sNullFunc()); } + + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != nonNull(ptr)); } + bool operator ==(Type* ptr) const { return (mPointer == nonNull(ptr)); } + bool operator ==(const LLHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); } + + LLHandle<Type>& operator =(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = nonNull(ptr); + ref(); + } + + return *this; + } + + LLHandle<Type>& operator =(const LLHandle<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> + LLHandle<Type>& operator =(const LLHandle<Subclass>& ptr) + { + if( mPointer != ptr.get() ) + { + unref(); + mPointer = ptr.get(); + ref(); + } + return *this; + } + +public: + typedef Type* (*NullFunc)(); + static const NullFunc sNullFunc; + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = sNullFunc(); + tempp->unref(); + if (mPointer != sNullFunc()) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + + static Type* nonNull(Type* ptr) + { + return ptr == NULL ? sNullFunc() : ptr; + } + + static Type* defaultNullFunc() + { + llerrs << "No null value provided for LLHandle" << llendl; + return NULL; + } + +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> > |