summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llhandle.h216
-rw-r--r--indra/llcommon/llinitparam.h108
-rw-r--r--indra/llcommon/llversionviewer.h2
4 files changed, 272 insertions, 55 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..401e4d759a
--- /dev/null
+++ b/indra/llcommon/llhandle.h
@@ -0,0 +1,216 @@
+/**
+* @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>
+
+/**
+ * Helper object for LLHandle. Don't instantiate these directly, used
+ * exclusively by LLHandle.
+ */
+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
+ *
+ * The implementation is like some "weak pointer" implementations. When we
+ * can't control the lifespan of the referenced object of interest, we can
+ * still instantiate a proxy object whose lifespan we DO control, and store in
+ * the proxy object a dumb pointer to the actual target. Then we just have to
+ * ensure that on destruction of the target object, the proxy's dumb pointer
+ * is set NULL.
+ *
+ * LLTombStone is our proxy object. LLHandle contains an LLPointer to the
+ * LLTombStone, so every copy of an LLHandle increments the LLTombStone's ref
+ * count as usual.
+ *
+ * One copy of the LLHandle, specifically the LLRootHandle, must be stored in
+ * the referenced object. Destroying the LLRootHandle is what NULLs the
+ * proxy's target pointer.
+ *
+ * Minor optimization: we want LLHandle's mTombStone to always be a valid
+ * LLPointer, saving some conditionals in dereferencing. That's the
+ * getDefaultTombStone() mechanism. The default LLTombStone object's target
+ * pointer is always NULL, so it's semantically identical to allowing
+ * mTombStone to be invalid.
+ */
+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;
+ }
+};
+
+/**
+ * LLRootHandle isa LLHandle which must be stored in the referenced object.
+ * You can either store it directly and explicitly bind(this), or derive from
+ * LLHandleProvider (q.v.) which automates that for you. The essential point
+ * is that destroying the LLRootHandle (as a consequence of destroying the
+ * referenced object) calls unbind(), setting the LLTombStone's target pointer
+ * NULL.
+ */
+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;
+ }
+
+ 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;
+ }
+
+protected:
+ typedef LLHandle<T> handle_type_t;
+ LLHandleProvider()
+ {
+ // provided here to enforce T deriving from LLHandleProvider<T>
+ }
+
+private:
+ mutable LLRootHandle<T> mHandle;
+};
+
+#endif
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index be07ccc0f8..97133c99d7 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -438,7 +438,7 @@ namespace LLInitParam
{}
void operator ()(const std::string& name)
- {
+ {
*this = name;
}
@@ -625,38 +625,38 @@ namespace LLInitParam
class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
};
- //TODO: implement in terms of owned_ptr
- template<typename T>
+ //TODO: implement in terms of owned_ptr
+ template<typename T>
class LazyValue
- {
+ {
public:
LazyValue()
- : mPtr(NULL)
- {}
+ : mPtr(NULL)
+ {}
~LazyValue()
- {
- delete mPtr;
- }
+ {
+ delete mPtr;
+ }
LazyValue(const T& value)
- {
+ {
mPtr = new T(value);
}
LazyValue(const LazyValue& other)
: mPtr(NULL)
- {
+ {
*this = other;
- }
+ }
LazyValue& operator = (const LazyValue& other)
- {
+ {
if (!other.mPtr)
{
delete mPtr;
- mPtr = NULL;
- }
+ mPtr = NULL;
+ }
else
{
if (!mPtr)
@@ -667,9 +667,9 @@ namespace LLInitParam
{
*mPtr = *(other.mPtr);
}
+ }
+ return *this;
}
- return *this;
- }
bool operator==(const LazyValue& other) const
{
@@ -677,13 +677,13 @@ namespace LLInitParam
return *mPtr == *other.mPtr;
}
- bool empty() const
- {
- return mPtr == NULL;
- }
+ bool empty() const
+ {
+ return mPtr == NULL;
+ }
- void set(const T& other)
- {
+ void set(const T& other)
+ {
if (!mPtr)
{
mPtr = new T(other);
@@ -694,36 +694,36 @@ namespace LLInitParam
}
}
- const T& get() const
- {
+ const T& get() const
+ {
return *ensureInstance();
- }
+ }
- T& get()
- {
+ T& get()
+ {
return *ensureInstance();
}
operator const T&() const
{
return get();
- }
+ }
- private:
- // lazily allocate an instance of T
- T* ensureInstance() const
- {
- if (mPtr == NULL)
+ private:
+ // lazily allocate an instance of T
+ T* ensureInstance() const
{
- mPtr = new T();
- }
- return mPtr;
- }
+ if (mPtr == NULL)
+ {
+ mPtr = new T();
+ }
+ return mPtr;
+ }
- private:
+ private:
- mutable T* mPtr;
- };
+ mutable T* mPtr;
+ };
// root class of all parameter blocks
@@ -905,7 +905,7 @@ namespace LLInitParam
}
U32 getEnclosingBlockOffset() const
- {
+ {
return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;
}
@@ -2063,7 +2063,7 @@ namespace LLInitParam
// dummy writer interfaces
template<typename T>
Deprecated& operator =(const T& val)
- {
+ {
// do nothing
return *this;
}
@@ -2197,9 +2197,9 @@ namespace LLInitParam
}
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
+ {
return mValue.inspectBlock(p, name_stack, min_count, max_count);
- }
+ }
bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
{
@@ -2209,7 +2209,7 @@ namespace LLInitParam
// clear away what is there and take the new stuff as a whole
resetToDefault();
return mValue.mergeBlock(block_data, source.getValue(), overwrite);
- }
+ }
return mValue.mergeBlock(block_data, source.getValue(), overwrite);
@@ -2281,7 +2281,7 @@ namespace LLInitParam
if (new_name)
{
mCurParam = getBlockDescriptor().mAllParams.begin();
- }
+ }
if (name_stack_range.first == name_stack_range.second
&& mCurParam != getBlockDescriptor().mAllParams.end())
{
@@ -2293,7 +2293,7 @@ namespace LLInitParam
if (deserialize_func
&& paramp
&& deserialize_func(*paramp, p, name_stack_range, new_name))
- {
+ {
++mCurParam;
return true;
}
@@ -2301,7 +2301,7 @@ namespace LLInitParam
{
return false;
}
- }
+ }
else
{
return mValue.deserializeBlock(p, name_stack_range, new_name);
@@ -2358,7 +2358,7 @@ namespace LLInitParam
: T(),
mValidated(false)
{}
-
+
ParamValue(const default_value_t& value)
: T(value.getValue()),
mValidated(false)
@@ -2430,7 +2430,7 @@ namespace LLInitParam
{
return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);
}
-
+
bool validateBlock(bool emit_errors = true) const
{
return mValue.empty() || mValue.get().validateBlock(emit_errors);
@@ -2545,10 +2545,10 @@ namespace LLInitParam
} EValueAge;
typedef ParamValue<T> derived_t;
- typedef CustomParamValue<T> self_t;
- typedef Block<derived_t> block_t;
+ typedef CustomParamValue<T> self_t;
+ typedef Block<derived_t> block_t;
typedef T default_value_t;
- typedef T value_t;
+ typedef T value_t;
typedef void baseblock_base_class_t;
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index bcc661a920..b12aa8826a 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 4;
-const S32 LL_VERSION_PATCH = 1;
+const S32 LL_VERSION_PATCH = 2;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";