Skip to content

Commit

Permalink
Merge pull request #2681 from secondlife/nat/xcode-16
Browse files Browse the repository at this point in the history
Generalize LLPointer's comparison operators to allow comparable LLPointer types.
  • Loading branch information
marchcat committed Sep 25, 2024
2 parents 576c558 + 5d7b3ab commit 4b2b94f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 202 deletions.
256 changes: 55 additions & 201 deletions indra/llcommon/llpointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "llerror.h" // *TODO: consider eliminating this
#include "llmutex.h"
#include <utility> // std::swap()

//----------------------------------------------------------------------------
// RefCount objects should generally only be accessed by way of LLPointer<>'s
Expand Down Expand Up @@ -60,6 +61,13 @@ template <class Type> class LLPointer
ref();
}

// Even though the template constructors below accepting
// (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to
// subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&)
// constructors, the compiler recognizes these as The Copy Constructor and
// The Move Constructor, respectively. In other words, even in the
// presence of the LLPointer<Subclass> constructors, we still must specify
// the LLPointer<Type> constructors.
LLPointer(const LLPointer<Type>& ptr) :
mPointer(ptr.mPointer)
{
Expand Down Expand Up @@ -105,61 +113,79 @@ template <class Type> class LLPointer
bool notNull() const { return (mPointer != nullptr); }

operator Type*() const { return mPointer; }
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
template <typename Type1>
bool operator !=(Type1* ptr) const { return (mPointer != ptr); }
template <typename Type1>
bool operator ==(Type1* ptr) const { return (mPointer == ptr); }
template <typename Type1>
bool operator !=(const LLPointer<Type1>& ptr) const { return (mPointer != ptr.mPointer); }
template <typename Type1>
bool operator ==(const LLPointer<Type1>& ptr) const { return (mPointer == ptr.mPointer); }
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }

LLPointer<Type>& operator =(Type* ptr)
{
assign(ptr);
// copy-and-swap idiom, see http://gotw.ca/gotw/059.htm
LLPointer temp(ptr);
using std::swap; // per Swappable convention
swap(*this, temp);
return *this;
}

// Even though the template assignment operators below accepting
// (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to
// subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&)
// assignment operators, the compiler recognizes these as Copy Assignment
// and Move Assignment, respectively. In other words, even in the presence
// of the LLPointer<Subclass> assignment operators, we still must specify
// the LLPointer<Type> operators.
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
{
assign(ptr);
LLPointer temp(ptr);
using std::swap; // per Swappable convention
swap(*this, temp);
return *this;
}

LLPointer<Type>& operator =(LLPointer<Type>&& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ptr.mPointer = nullptr;
}
LLPointer temp(std::move(ptr));
using std::swap; // per Swappable convention
swap(*this, temp);
return *this;
}

// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass>
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
{
assign(ptr.get());
LLPointer temp(ptr);
using std::swap; // per Swappable convention
swap(*this, temp);
return *this;
}

template<typename Subclass>
LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ptr.mPointer = nullptr;
}
LLPointer temp(std::move(ptr));
using std::swap; // per Swappable convention
swap(*this, temp);
return *this;
}

// Just exchange the pointers, which will not change the reference counts.
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
{
Type* temp = a.mPointer;
a.mPointer = b.mPointer;
b.mPointer = temp;
using std::swap; // per Swappable convention
swap(a.mPointer, b.mPointer);
}

// Put swap() overload in the global namespace, per Swappable convention
friend void swap(LLPointer<Type>& a, LLPointer<Type>& b)
{
LLPointer<Type>::swap(a, b);
}

protected:
Expand Down Expand Up @@ -191,184 +217,12 @@ template <class Type> class LLPointer
}
#endif // LL_LIBRARY_INCLUDE

void assign(const LLPointer<Type>& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ref();
}
}

protected:
Type* mPointer;
};

template <class Type> class LLConstPointer
{
template<typename Subclass>
friend class LLConstPointer;
public:
LLConstPointer() :
mPointer(nullptr)
{
}

LLConstPointer(const Type* ptr) :
mPointer(ptr)
{
ref();
}

LLConstPointer(const LLConstPointer<Type>& ptr) :
mPointer(ptr.mPointer)
{
ref();
}

LLConstPointer(LLConstPointer<Type>&& ptr) noexcept
{
mPointer = ptr.mPointer;
ptr.mPointer = nullptr;
}

// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass>
LLConstPointer(const LLConstPointer<Subclass>& ptr) :
mPointer(ptr.get())
{
ref();
}

template<typename Subclass>
LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept :
mPointer(ptr.get())
{
ptr.mPointer = nullptr;
}

~LLConstPointer()
{
unref();
}

const Type* get() const { return mPointer; }
const Type* operator->() const { return mPointer; }
const Type& operator*() const { return *mPointer; }

operator BOOL() const { return (mPointer != nullptr); }
operator bool() const { return (mPointer != nullptr); }
bool operator!() const { return (mPointer == nullptr); }
bool isNull() const { return (mPointer == nullptr); }
bool notNull() const { return (mPointer != nullptr); }

operator const Type*() const { return mPointer; }
bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }

LLConstPointer<Type>& operator =(const Type* ptr)
{
if( mPointer != ptr )
{
unref();
mPointer = ptr;
ref();
}

return *this;
}

LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
{
if( mPointer != ptr.mPointer )
{
unref();
mPointer = ptr.mPointer;
ref();
}
return *this;
}

LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ptr.mPointer = nullptr;
}
return *this;
}

// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass>
LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
{
if( mPointer != ptr.get() )
{
unref();
mPointer = ptr.get();
ref();
}
return *this;
}

template<typename Subclass>
LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ptr.mPointer = nullptr;
}
return *this;
}

// Just exchange the pointers, which will not change the reference counts.
static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
{
const Type* temp = a.mPointer;
a.mPointer = b.mPointer;
b.mPointer = temp;
}

protected:
#ifdef LL_LIBRARY_INCLUDE
void ref();
void unref();
#else // LL_LIBRARY_INCLUDE
void ref()
{
if (mPointer)
{
mPointer->ref();
}
}

void unref()
{
if (mPointer)
{
const Type *temp = mPointer;
mPointer = nullptr;
temp->unref();
if (mPointer != nullptr)
{
LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
unref();
}
}
}
#endif // LL_LIBRARY_INCLUDE

protected:
const Type* mPointer;
};
template <typename Type>
using LLConstPointer = LLPointer<const Type>;

template<typename Type>
class LLCopyOnWritePointer : public LLPointer<Type>
Expand Down Expand Up @@ -418,14 +272,14 @@ class LLCopyOnWritePointer : public LLPointer<Type>
bool mStayUnique;
};

template<typename Type>
bool operator!=(Type* lhs, const LLPointer<Type>& rhs)
template<typename Type0, typename Type1>
bool operator!=(Type0* lhs, const LLPointer<Type1>& rhs)
{
return (lhs != rhs.get());
}

template<typename Type>
bool operator==(Type* lhs, const LLPointer<Type>& rhs)
template<typename Type0, typename Type1>
bool operator==(Type0* lhs, const LLPointer<Type1>& rhs)
{
return (lhs == rhs.get());
}
Expand Down
2 changes: 1 addition & 1 deletion indra/newview/llviewerwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
// Check the whitelist, if there's media (otherwise just show it)
if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
{
if (obj != mDragHoveredObject.get())
if (obj != mDragHoveredObject)
{
// Highlight the dragged object
LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
Expand Down

0 comments on commit 4b2b94f

Please sign in to comment.