PageRenderTime 11ms CodeModel.GetById 1ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llpointer.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 170 lines | 109 code | 22 blank | 39 comment | 18 complexity | 05aa359c8eb237bb0aa0f2cecd897fcb MD5 | raw file
  1/** 
  2 * @file llpointer.h
  3 * @brief A reference-counted pointer for objects derived from LLRefCount
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26#ifndef LLPOINTER_H
 27#define LLPOINTER_H
 28
 29#include "llerror.h"	// *TODO: consider eliminating this
 30
 31//----------------------------------------------------------------------------
 32// RefCount objects should generally only be accessed by way of LLPointer<>'s
 33// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
 34//   if LLFoo::LLFoo() does anything like put itself in an update queue.
 35//   The queue may get accessed before it gets assigned to x.
 36// The correct implementation is:
 37//   LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
 38//   x->instantiate(); // does stuff like place x into an update queue
 39
 40// see llthread.h for LLThreadSafeRefCount
 41
 42//----------------------------------------------------------------------------
 43
 44// Note: relies on Type having ref() and unref() methods
 45template <class Type> class LLPointer
 46{
 47public:
 48
 49	LLPointer() : 
 50		mPointer(NULL)
 51	{
 52	}
 53
 54	LLPointer(Type* ptr) : 
 55		mPointer(ptr)
 56	{
 57		ref();
 58	}
 59
 60	LLPointer(const LLPointer<Type>& ptr) : 
 61		mPointer(ptr.mPointer)
 62	{
 63		ref();
 64	}
 65
 66	// support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.
 67	template<typename Subclass>
 68	LLPointer(const LLPointer<Subclass>& ptr) : 
 69		mPointer(ptr.get())
 70	{
 71		ref();
 72	}
 73
 74	~LLPointer()								
 75	{
 76		unref();
 77	}
 78
 79	Type*	get() const							{ return mPointer; }
 80	const Type*	operator->() const				{ return mPointer; }
 81	Type*	operator->()						{ return mPointer; }
 82	const Type&	operator*() const				{ return *mPointer; }
 83	Type&	operator*()							{ return *mPointer; }
 84
 85	operator BOOL()  const						{ return (mPointer != NULL); }
 86	operator bool()  const						{ return (mPointer != NULL); }
 87	bool operator!() const						{ return (mPointer == NULL); }
 88	bool isNull() const							{ return (mPointer == NULL); }
 89	bool notNull() const						{ return (mPointer != NULL); }
 90
 91	operator Type*()       const				{ return mPointer; }
 92	bool operator !=(Type* ptr) const           { return (mPointer != ptr); 	}
 93	bool operator ==(Type* ptr) const           { return (mPointer == ptr); 	}
 94	bool operator ==(const LLPointer<Type>& ptr) const           { return (mPointer == ptr.mPointer); 	}
 95	bool operator < (const LLPointer<Type>& ptr) const           { return (mPointer < ptr.mPointer); 	}
 96	bool operator > (const LLPointer<Type>& ptr) const           { return (mPointer > ptr.mPointer); 	}
 97
 98	LLPointer<Type>& operator =(Type* ptr)                   
 99	{ 
100		if( mPointer != ptr )
101		{
102			unref(); 
103			mPointer = ptr; 
104			ref();
105		}
106
107		return *this; 
108	}
109
110	LLPointer<Type>& operator =(const LLPointer<Type>& ptr)  
111	{ 
112		if( mPointer != ptr.mPointer )
113		{
114			unref(); 
115			mPointer = ptr.mPointer;
116			ref();
117		}
118		return *this; 
119	}
120
121	// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
122	template<typename Subclass>
123	LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)  
124	{ 
125		if( mPointer != ptr.get() )
126		{
127			unref(); 
128			mPointer = ptr.get();
129			ref();
130		}
131		return *this; 
132	}
133	
134	// Just exchange the pointers, which will not change the reference counts.
135	static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
136	{
137		Type* temp = a.mPointer;
138		a.mPointer = b.mPointer;
139		b.mPointer = temp;
140	}
141
142protected:
143	void ref()                             
144	{ 
145		if (mPointer)
146		{
147			mPointer->ref();
148		}
149	}
150
151	void unref()
152	{
153		if (mPointer)
154		{
155			Type *tempp = mPointer;
156			mPointer = NULL;
157			tempp->unref();
158			if (mPointer != NULL)
159			{
160				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
161				unref();
162			}
163		}
164	}
165
166protected:
167	Type*	mPointer;
168};
169
170#endif