From 98c829a47cd2b38d51602cce3de873179a394ba7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 25 Sep 2024 09:43:43 -0400 Subject: Use copy-and-swap idiom for LLPointer's assignment operators. This affords strong exception safety. Also, eliminating the conditional may improve speed. --- indra/llcommon/llpointer.h | 53 ++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index bbe3595435..c5dd5532cc 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -28,6 +28,7 @@ #include "llerror.h" // *TODO: consider eliminating this #include "llmutex.h" +#include // std::swap() //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s @@ -118,24 +119,26 @@ public: LLPointer& 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; } LLPointer& operator =(const LLPointer& ptr) { - assign(ptr); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } LLPointer& operator =(LLPointer&& 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; } @@ -143,28 +146,32 @@ public: template LLPointer& operator =(const LLPointer& ptr) { - assign(ptr.get()); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } template LLPointer& operator =(LLPointer&& 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& a, LLPointer& 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& a, LLPointer& b) + { + LLPointer::swap(a, b); } protected: @@ -196,16 +203,6 @@ protected: } #endif // LL_LIBRARY_INCLUDE - void assign(const LLPointer& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - } - protected: Type* mPointer; }; -- cgit v1.2.3