diff options
Diffstat (limited to 'indra/llcommon/llpointer.h')
-rwxr-xr-x[-rw-r--r--] | indra/llcommon/llpointer.h | 225 |
1 files changed, 196 insertions, 29 deletions
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index e6c736a263..9a6453ea48 100644..100755 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -2,37 +2,32 @@ * @file llpointer.h * @brief A reference-counted pointer for objects derived from LLRefCount * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLPOINTER_H #define LLPOINTER_H #include "llerror.h" // *TODO: consider eliminating this +#include "llmutex.h" //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s @@ -103,6 +98,126 @@ public: LLPointer<Type>& operator =(Type* ptr) { + assign(ptr); + return *this; + } + + LLPointer<Type>& operator =(const LLPointer<Type>& ptr) + { + assign(ptr); + 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) + { + assign(ptr.get()); + return *this; + } + + // Just exchange the pointers, which will not change the reference counts. + static void swap(LLPointer<Type>& a, LLPointer<Type>& b) + { + Type* temp = a.mPointer; + a.mPointer = b.mPointer; + b.mPointer = temp; + } + +protected: +#ifdef LL_LIBRARY_INCLUDE + void ref(); + void unref(); +#else + + void assign(const LLPointer<Type>& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + } + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *temp = mPointer; + mPointer = NULL; + temp->unref(); + if (mPointer != NULL) + { + LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; + unref(); + } + } + } +#endif +protected: + Type* mPointer; +}; + +template <class Type> class LLConstPointer +{ +public: + LLConstPointer() : + mPointer(NULL) + { + } + + LLConstPointer(const Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLConstPointer(const LLConstPointer<Type>& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template<typename Subclass> + LLConstPointer(const LLConstPointer<Subclass>& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLConstPointer() + { + unref(); + } + + const Type* get() const { return mPointer; } + const Type* operator->() const { return mPointer; } + const Type& operator*() const { 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 const Type*() const { return mPointer; } + bool operator !=(const Type* ptr) const { return (mPointer != ptr); } + bool operator ==(const Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } + + LLConstPointer<Type>& operator =(const Type* ptr) + { if( mPointer != ptr ) { unref(); @@ -113,7 +228,7 @@ public: return *this; } - LLPointer<Type>& operator =(const LLPointer<Type>& ptr) + LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr) { if( mPointer != ptr.mPointer ) { @@ -126,7 +241,7 @@ public: // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template<typename Subclass> - LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) + LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) { if( mPointer != ptr.get() ) { @@ -138,14 +253,18 @@ public: } // Just exchange the pointers, which will not change the reference counts. - static void swap(LLPointer<Type>& a, LLPointer<Type>& b) + static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) { - Type* temp = a.mPointer; + const Type* temp = a.mPointer; a.mPointer = b.mPointer; b.mPointer = temp; } protected: +#ifdef LL_LIBRARY_INCLUDE + void ref(); + void unref(); +#else void ref() { if (mPointer) @@ -158,19 +277,67 @@ protected: { if (mPointer) { - Type *tempp = mPointer; + const Type *tempp = mPointer; mPointer = NULL; tempp->unref(); if (mPointer != NULL) { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; unref(); } } } - +#endif protected: - Type* mPointer; + const Type* mPointer; +}; + +template<typename Type> +class LLCopyOnWritePointer : public LLPointer<Type> +{ +public: + typedef LLCopyOnWritePointer<Type> self_t; + typedef LLPointer<Type> pointer_t; + + LLCopyOnWritePointer() + : mStayUnique(false) + {} + + LLCopyOnWritePointer(Type* ptr) + : LLPointer<Type>(ptr), + mStayUnique(false) + {} + + LLCopyOnWritePointer(LLPointer<Type>& ptr) + : LLPointer<Type>(ptr), + mStayUnique(false) + { + if (ptr.mForceUnique) + { + makeUnique(); + } + } + + Type* write() + { + makeUnique(); + return pointer_t::mPointer; + } + + void makeUnique() + { + if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1) + { + *(pointer_t* )(this) = new Type(*pointer_t::mPointer); + } + } + + const Type* operator->() const { return pointer_t::mPointer; } + const Type& operator*() const { return *pointer_t::mPointer; } + + void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; } +private: + bool mStayUnique; }; #endif |