summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2012-08-08 13:23:02 -0400
committerNat Goodspeed <nat@lindenlab.com>2012-08-08 13:23:02 -0400
commit50f3e227a2ba511a1110b3e5a214db73ba3cc4e8 (patch)
treeb8444cf2ff47b66743ecf304c24b3fcb04e9deba /indra/llcommon
parentac7f7366cd8147f7826c6d59584c96ecf6115c61 (diff)
Move llhandle.h into llcommon; same generality as llpointer.h.
Leaving llhandle.h in llui restricts the set of viewer project directories which could potentially use it, and there's nothing whatsoever UI-specific about it.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llhandle.h181
2 files changed, 182 insertions, 0 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index dd7b8c6eb8..36a8319189 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -174,6 +174,7 @@ set(llcommon_HEADER_FILES
llfoldertype.h
llformat.h
llframetimer.h
+ llhandle.h
llhash.h
llheartbeat.h
llhttpstatuscodes.h
diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h
new file mode 100644
index 0000000000..37c657dd92
--- /dev/null
+++ b/indra/llcommon/llhandle.h
@@ -0,0 +1,181 @@
+/**
+* @file llhandle.h
+* @brief "Handle" to an object (usually a floater) whose lifetime you don't
+* control.
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* 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.
+*
+* 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.
+*
+* 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 LLHANDLE_H
+#define LLHANDLE_H
+
+#include "llpointer.h"
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
+
+class LLTombStone : public LLRefCount
+{
+public:
+ LLTombStone(void* target = NULL) : mTarget(target) {}
+
+ void setTarget(void* target) { mTarget = target; }
+ void* getTarget() const { return mTarget; }
+private:
+ mutable void* mTarget;
+};
+
+// LLHandles are used to refer to objects whose lifetime you do not control or influence.
+// Calling get() on a handle will return a pointer to the referenced object or NULL,
+// if the object no longer exists. Note that during the lifetime of the returned pointer,
+// you are assuming that the object will not be deleted by any action you perform,
+// or any other thread, as normal when using pointers, so avoid using that pointer outside of
+// the local code block.
+//
+// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
+
+template <typename T>
+class LLHandle
+{
+ template <typename U> friend class LLHandle;
+ template <typename U> friend class LLHandleProvider;
+public:
+ LLHandle() : mTombStone(getDefaultTombStone()) {}
+
+ template<typename U>
+ LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
+ : mTombStone(other.mTombStone)
+ {}
+
+ bool isDead() const
+ {
+ return mTombStone->getTarget() == NULL;
+ }
+
+ void markDead()
+ {
+ mTombStone = getDefaultTombStone();
+ }
+
+ T* get() const
+ {
+ return reinterpret_cast<T*>(mTombStone->getTarget());
+ }
+
+ friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone == rhs.mTombStone;
+ }
+ friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return !(lhs == rhs);
+ }
+ friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone < rhs.mTombStone;
+ }
+ friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone > rhs.mTombStone;
+ }
+
+protected:
+ LLPointer<LLTombStone> mTombStone;
+
+private:
+ typedef T* pointer_t;
+ static LLPointer<LLTombStone>& getDefaultTombStone()
+ {
+ static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
+ return sDefaultTombStone;
+ }
+};
+
+template <typename T>
+class LLRootHandle : public LLHandle<T>
+{
+public:
+ typedef LLRootHandle<T> self_t;
+ typedef LLHandle<T> base_t;
+
+ LLRootHandle(T* object) { bind(object); }
+ LLRootHandle() {};
+ ~LLRootHandle() { unbind(); }
+
+ // this is redundant, since an LLRootHandle *is* an LLHandle
+ //LLHandle<T> getHandle() { return LLHandle<T>(*this); }
+
+ void bind(T* object)
+ {
+ // unbind existing tombstone
+ if (LLHandle<T>::mTombStone.notNull())
+ {
+ if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+ // tombstone reference counted, so no paired delete
+ LLHandle<T>::mTombStone = new LLTombStone((void*)object);
+ }
+
+ void unbind()
+ {
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+
+ //don't allow copying of root handles, since there should only be one
+private:
+ LLRootHandle(const LLRootHandle& other) {};
+};
+
+// Use this as a mixin for simple classes that need handles and when you don't
+// want handles at multiple points of the inheritance hierarchy
+template <typename T>
+class LLHandleProvider
+{
+public:
+ LLHandle<T> getHandle() const
+ {
+ // perform lazy binding to avoid small tombstone allocations for handle
+ // providers whose handles are never referenced
+ mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this)));
+ return mHandle;
+ }
+
+protected:
+ typedef LLHandle<T> handle_type_t;
+ LLHandleProvider()
+ {
+ // provided here to enforce T deriving from LLHandleProvider<T>
+ }
+
+ template <typename U>
+ LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
+ {
+ LLHandle<U> downcast_handle;
+ downcast_handle.mTombStone = getHandle().mTombStone;
+ return downcast_handle;
+ }
+
+
+private:
+ mutable LLRootHandle<T> mHandle;
+};
+
+#endif