Skip to content
Snippets Groups Projects
Commit 2d0e9112 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

Add implementation comments to LLHandle.

I recently tried to wade through llhandle.h and got somewhat perplexed. Armed
with an explanation from Richard, I've added notes to the file to try to make
it a bit less mysterious.
parent 50f3e227
No related branches found
No related tags found
No related merge requests found
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
/**
* Helper object for LLHandle. Don't instantiate these directly, used
* exclusively by LLHandle.
*/
class LLTombStone : public LLRefCount class LLTombStone : public LLRefCount
{ {
public: public:
...@@ -42,15 +46,37 @@ class LLTombStone : public LLRefCount ...@@ -42,15 +46,37 @@ class LLTombStone : public LLRefCount
mutable void* mTarget; 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, * LLHandles are used to refer to objects whose lifetime you do not control or influence.
// if the object no longer exists. Note that during the lifetime of the returned pointer, * Calling get() on a handle will return a pointer to the referenced object or NULL,
// you are assuming that the object will not be deleted by any action you perform, * if the object no longer exists. Note that during the lifetime of the returned pointer,
// or any other thread, as normal when using pointers, so avoid using that pointer outside of * you are assuming that the object will not be deleted by any action you perform,
// the local code block. * 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 *
* 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> template <typename T>
class LLHandle class LLHandle
{ {
...@@ -108,6 +134,14 @@ class LLHandle ...@@ -108,6 +134,14 @@ class LLHandle
} }
}; };
/**
* 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> template <typename T>
class LLRootHandle : public LLHandle<T> class LLRootHandle : public LLHandle<T>
{ {
...@@ -144,8 +178,10 @@ class LLRootHandle : public LLHandle<T> ...@@ -144,8 +178,10 @@ class LLRootHandle : public LLHandle<T>
LLRootHandle(const LLRootHandle& other) {}; 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 * 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> template <typename T>
class LLHandleProvider class LLHandleProvider
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment