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

/indra/llui/llhandle.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 181 lines | 113 code | 24 blank | 44 comment | 6 complexity | 7ee5cf18df404087e3eef6a0cc61528e MD5 | raw file
  1/** 
  2* @file llhandle.h
  3* @brief "Handle" to an object (usually a floater) whose lifetime you don't
  4* control.
  5*
  6* $LicenseInfo:firstyear=2001&license=viewerlgpl$
  7* Second Life Viewer Source Code
  8* Copyright (C) 2010, Linden Research, Inc.
  9* 
 10* This library is free software; you can redistribute it and/or
 11* modify it under the terms of the GNU Lesser General Public
 12* License as published by the Free Software Foundation;
 13* version 2.1 of the License only.
 14* 
 15* This library is distributed in the hope that it will be useful,
 16* but WITHOUT ANY WARRANTY; without even the implied warranty of
 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18* Lesser General Public License for more details.
 19* 
 20* You should have received a copy of the GNU Lesser General Public
 21* License along with this library; if not, write to the Free Software
 22* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23* 
 24* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25* $/LicenseInfo$
 26*/
 27#ifndef LLHANDLE_H
 28#define LLHANDLE_H
 29
 30#include "llpointer.h"
 31#include <boost/type_traits/is_convertible.hpp>
 32#include <boost/utility/enable_if.hpp>
 33
 34class LLTombStone : public LLRefCount
 35{
 36public:
 37	LLTombStone(void* target = NULL) : mTarget(target) {}
 38
 39	void setTarget(void* target) { mTarget = target; }
 40	void* getTarget() const { return mTarget; }
 41private:
 42	mutable void* mTarget;
 43};
 44
 45//	LLHandles are used to refer to objects whose lifetime you do not control or influence.  
 46//	Calling get() on a handle will return a pointer to the referenced object or NULL, 
 47//	if the object no longer exists.  Note that during the lifetime of the returned pointer, 
 48//	you are assuming that the object will not be deleted by any action you perform, 
 49//	or any other thread, as normal when using pointers, so avoid using that pointer outside of
 50//	the local code block.
 51// 
 52//  https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
 53
 54template <typename T>
 55class LLHandle
 56{
 57	template <typename U> friend class LLHandle;
 58	template <typename U> friend class LLHandleProvider;
 59public:
 60	LLHandle() : mTombStone(getDefaultTombStone()) {}
 61
 62	template<typename U>
 63	LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
 64	: mTombStone(other.mTombStone)
 65	{}
 66
 67	bool isDead() const 
 68	{ 
 69		return mTombStone->getTarget() == NULL; 
 70	}
 71
 72	void markDead() 
 73	{ 
 74		mTombStone = getDefaultTombStone();
 75	}
 76
 77	T* get() const
 78	{
 79		return reinterpret_cast<T*>(mTombStone->getTarget());
 80	}
 81
 82	friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
 83	{
 84		return lhs.mTombStone == rhs.mTombStone;
 85	}
 86	friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
 87	{
 88		return !(lhs == rhs);
 89	}
 90	friend bool	operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
 91	{
 92		return lhs.mTombStone < rhs.mTombStone;
 93	}
 94	friend bool	operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
 95	{
 96		return lhs.mTombStone > rhs.mTombStone;
 97	}
 98
 99protected:
100	LLPointer<LLTombStone> mTombStone;
101
102private:
103	typedef T* pointer_t;
104	static LLPointer<LLTombStone>& getDefaultTombStone()
105	{
106		static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
107		return sDefaultTombStone;
108	}
109};
110
111template <typename T>
112class LLRootHandle : public LLHandle<T>
113{
114public:
115	typedef LLRootHandle<T> self_t;
116	typedef LLHandle<T> base_t;
117
118	LLRootHandle(T* object) { bind(object); }
119	LLRootHandle() {};
120	~LLRootHandle() { unbind(); }
121
122	// this is redundant, since an LLRootHandle *is* an LLHandle
123	//LLHandle<T> getHandle() { return LLHandle<T>(*this); }
124
125	void bind(T* object) 
126	{ 
127		// unbind existing tombstone
128		if (LLHandle<T>::mTombStone.notNull())
129		{
130			if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
131			LLHandle<T>::mTombStone->setTarget(NULL);
132		}
133		// tombstone reference counted, so no paired delete
134		LLHandle<T>::mTombStone = new LLTombStone((void*)object);
135	}
136
137	void unbind() 
138	{
139		LLHandle<T>::mTombStone->setTarget(NULL);
140	}
141
142	//don't allow copying of root handles, since there should only be one
143private:
144	LLRootHandle(const LLRootHandle& other) {};
145};
146
147// Use this as a mixin for simple classes that need handles and when you don't
148// want handles at multiple points of the inheritance hierarchy
149template <typename T>
150class LLHandleProvider
151{
152public:
153	LLHandle<T> getHandle() const
154	{ 
155		// perform lazy binding to avoid small tombstone allocations for handle
156		// providers whose handles are never referenced
157		mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this))); 
158		return mHandle; 
159	}
160
161protected:
162	typedef LLHandle<T> handle_type_t;
163	LLHandleProvider() 
164	{
165		// provided here to enforce T deriving from LLHandleProvider<T>
166	} 
167
168	template <typename U>
169	LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
170	{
171		LLHandle<U> downcast_handle;
172		downcast_handle.mTombStone = getHandle().mTombStone;
173		return downcast_handle;
174	}
175
176
177private:
178	mutable LLRootHandle<T> mHandle;
179};
180
181#endif