Update to LLTombstone/LLHandle/LLRootHandle/LLHandleProvider.
This commit is contained in:
@@ -148,7 +148,6 @@ LLFloater::LLFloater() :
|
||||
mResizeHandle[i] = NULL;
|
||||
}
|
||||
mDragHandle = NULL;
|
||||
mHandle.bind(this);
|
||||
mNotificationContext = new LLFloaterNotificationContext(getHandle());
|
||||
}
|
||||
|
||||
@@ -222,7 +221,6 @@ void LLFloater::initFloater(const std::string& title,
|
||||
BOOL resizable, S32 min_width, S32 min_height,
|
||||
BOOL drag_on_left, BOOL minimizable, BOOL close_btn)
|
||||
{
|
||||
mHandle.bind(this);
|
||||
mNotificationContext = new LLFloaterNotificationContext(getHandle());
|
||||
|
||||
// Init function can be called more than once, so clear out old data.
|
||||
@@ -422,7 +420,7 @@ void LLFloater::initFloater(const std::string& title,
|
||||
setVisible(FALSE);
|
||||
|
||||
// add self to handle->floater map
|
||||
sFloaterMap[mHandle] = this;
|
||||
sFloaterMap[getHandle()] = this;
|
||||
|
||||
if (!getParent())
|
||||
{
|
||||
@@ -483,7 +481,7 @@ LLFloater::~LLFloater()
|
||||
// correct, non-minimized positions.
|
||||
setMinimized( FALSE );
|
||||
|
||||
sFloaterMap.erase(mHandle);
|
||||
sFloaterMap.erase(getHandle());
|
||||
|
||||
delete mDragHandle;
|
||||
for (S32 i = 0; i < 4; i++)
|
||||
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
void clearSnapTarget() { mSnappedTo.markDead(); }
|
||||
LLHandle<LLFloater> getSnapTarget() const { return mSnappedTo; }
|
||||
|
||||
LLHandle<LLFloater> getHandle() const { return mHandle; }
|
||||
LLHandle<LLFloater> getHandle() const { return getDerivedHandle<LLFloater>(); }
|
||||
|
||||
// Return a closeable floater, if any, given the current focus.
|
||||
static LLFloater* getClosableFloaterFromFocus();
|
||||
@@ -331,7 +331,6 @@ private:
|
||||
S32 mPreviousMinimizedLeft;
|
||||
|
||||
LLFloaterNotificationContext* mNotificationContext;
|
||||
LLRootHandle<LLFloater> mHandle;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -28,38 +28,67 @@
|
||||
#define LLHANDLE_H
|
||||
|
||||
#include "llpointer.h"
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
template <typename T>
|
||||
/**
|
||||
* Helper object for LLHandle. Don't instantiate these directly, used
|
||||
* exclusively by LLHandle.
|
||||
*/
|
||||
class LLTombStone : public LLRefCount
|
||||
{
|
||||
public:
|
||||
LLTombStone(T* target = NULL) : mTarget(target) {}
|
||||
LLTombStone(void* target = NULL) : mTarget(target) {}
|
||||
|
||||
void setTarget(T* target) { mTarget = target; }
|
||||
T* getTarget() const { return mTarget; }
|
||||
void setTarget(void* target) { mTarget = target; }
|
||||
void* getTarget() const { return mTarget; }
|
||||
private:
|
||||
T* 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,
|
||||
// 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
|
||||
|
||||
/**
|
||||
* 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()) {}
|
||||
const LLHandle<T>& operator =(const LLHandle<T>& other)
|
||||
{
|
||||
mTombStone = other.mTombStone;
|
||||
return *this;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
@@ -73,7 +102,7 @@ public:
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return mTombStone->getTarget();
|
||||
return reinterpret_cast<T*>(mTombStone->getTarget());
|
||||
}
|
||||
|
||||
friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
|
||||
@@ -94,37 +123,49 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
LLPointer<LLTombStone<T> > mTombStone;
|
||||
LLPointer<LLTombStone> mTombStone;
|
||||
|
||||
private:
|
||||
static LLPointer<LLTombStone<T> >& getDefaultTombStone()
|
||||
typedef T* pointer_t;
|
||||
static LLPointer<LLTombStone>& getDefaultTombStone()
|
||||
{
|
||||
static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>;
|
||||
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 a LLRootHandle *is* an LLHandle
|
||||
LLHandle<T> getHandle() { return LLHandle<T>(*this); }
|
||||
// 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() == object) return;
|
||||
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<T>(object);
|
||||
LLHandle<T>::mTombStone = new LLTombStone((void*)object);
|
||||
}
|
||||
|
||||
void unbind()
|
||||
@@ -137,11 +178,22 @@ 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
|
||||
/**
|
||||
* 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()
|
||||
@@ -149,16 +201,17 @@ protected:
|
||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||
}
|
||||
|
||||
LLHandle<T> getHandle()
|
||||
{
|
||||
// perform lazy binding to avoid small tombstone allocations for handle
|
||||
// providers whose handles are never referenced
|
||||
mHandle.bind(static_cast<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;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
LLRootHandle<T> mHandle;
|
||||
mutable LLRootHandle<T> mHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -80,7 +80,6 @@ void LLPanel::init()
|
||||
mDefaultBtn = NULL;
|
||||
setIsChrome(FALSE); //is this a decorator to a live window or a form?
|
||||
|
||||
mPanelHandle.bind(this);
|
||||
setTabStop(FALSE);
|
||||
mVisibleSignal = NULL;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
|
||||
void setCtrlsEnabled(BOOL b);
|
||||
|
||||
LLHandle<LLPanel> getHandle() const { return mPanelHandle; }
|
||||
LLHandle<LLPanel> getHandle() const { return getDerivedHandle<LLPanel>(); }
|
||||
|
||||
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
|
||||
|
||||
@@ -246,7 +246,6 @@ private:
|
||||
LLViewBorder* mBorder;
|
||||
LLButton* mDefaultBtn;
|
||||
std::string mLabel;
|
||||
LLRootHandle<LLPanel> mPanelHandle;
|
||||
|
||||
typedef std::map<std::string, std::string> ui_string_map_t;
|
||||
ui_string_map_t mUIStrings;
|
||||
|
||||
@@ -132,8 +132,8 @@ public:
|
||||
class LLView
|
||||
: public LLMouseHandler, // handles mouse events
|
||||
public LLFocusableElement, // handles keyboard events
|
||||
public LLMortician // lazy deletion
|
||||
//public LLHandleProvider<LLView> // passes out weak references to self
|
||||
public LLMortician, // lazy deletion
|
||||
public LLHandleProvider<LLView> // passes out weak references to self
|
||||
{
|
||||
public:
|
||||
struct Follows : public LLInitParam::ChoiceBlock<Follows>
|
||||
@@ -344,8 +344,6 @@ public:
|
||||
void popVisible() { setVisible(mLastVisible); }
|
||||
BOOL getLastVisible() const { return mLastVisible; }
|
||||
|
||||
LLHandle<LLView> getHandle() { mHandle.bind(this); return mHandle; }
|
||||
|
||||
U32 getFollows() const { return mReshapeFlags; }
|
||||
BOOL followsLeft() const { return mReshapeFlags & FOLLOWS_LEFT; }
|
||||
BOOL followsRight() const { return mReshapeFlags & FOLLOWS_RIGHT; }
|
||||
@@ -678,7 +676,6 @@ private:
|
||||
BOOL mIsFocusRoot;
|
||||
BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements
|
||||
|
||||
LLRootHandle<LLView> mHandle;
|
||||
BOOL mLastVisible;
|
||||
|
||||
S32 mNextInsertionOrdinal;
|
||||
|
||||
Reference in New Issue
Block a user