diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 7d07d0c3a7f3b53824988ada4ade8c3fda5d3f79..e15cea9ef260b4db3404a4a5bc9f8320e10f31d2 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -92,7 +92,10 @@ class LLSD::Impl public: static void reset(Impl*& var, Impl* impl); ///< safely set var to refer to the new impl (possibly shared) - + + static void move(Impl*& var, Impl*& impl); + ///< safely move impl from one object to another + static Impl& safe( Impl*); static const Impl& safe(const Impl*); ///< since a NULL Impl* is used for undefined, this ensures there is @@ -664,15 +667,30 @@ LLSD::Impl::~Impl() void LLSD::Impl::reset(Impl*& var, Impl* impl) { - if (impl && impl->mUseCount != STATIC_USAGE_COUNT) + if (var != impl) { - ++impl->mUseCount; + if (impl && impl->mUseCount != STATIC_USAGE_COUNT) + { + ++impl->mUseCount; + } + if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0) + { + delete var; + } + var = impl; } - if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0) +} + +void LLSD::Impl::move(Impl*& var, Impl*& impl) +{ + if (var == impl) return; // Bail out var is impl + + if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0) { - delete var; + delete var; // destroy var if usage falls to 0 and not static } - var = impl; + var = impl; // Steal impl to var without incrementing use since this is a move + impl = nullptr; // null out old-impl pointer } LLSD::Impl& LLSD::Impl::safe(Impl* impl) @@ -824,6 +842,8 @@ LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, nullptr); } LLSD::LLSD(const LLSD& other) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(other); } void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); } +LLSD::LLSD(LLSD&& other) noexcept : impl(nullptr) { ALLOC_LLSD_OBJECT; Impl::move(impl, other.impl); } +LLSD& LLSD::operator=(LLSD&& other) noexcept { Impl::move(impl, other.impl); return *this; } void LLSD::clear() { Impl::assignUndefined(impl); } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 24f72e4302f50d4d70024981d4497eec12a085b1..30ef6a8bdeb159765144d9d1c56503524e094a66 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -147,7 +147,7 @@ // Normally undefined, used for diagnostics //#define LLSD_DEBUG_INFO 1 -class LL_COMMON_API LLSD +class LL_COMMON_API LLSD final { public: LLSD(); ///< initially Undefined @@ -161,6 +161,12 @@ class LL_COMMON_API LLSD //@} + /** @name Movable */ + //@{ + LLSD(LLSD&& other) noexcept; + LLSD& operator=(LLSD&& other) noexcept; + //@} + void clear(); ///< resets to Undefined @@ -389,9 +395,9 @@ class LL_COMMON_API LLSD using an arbitrary pointer or scalar type to std::string. */ //@{ - LLSD(const void*); ///< construct from aribrary pointers - void assign(const void*); ///< assign from arbitrary pointers - LLSD& operator=(const void*); ///< assign from arbitrary pointers + LLSD(const void*) = delete; ///< construct from aribrary pointers + void assign(const void*) = delete; ///< assign from arbitrary pointers + LLSD& operator=(const void*) = delete; ///< assign from arbitrary pointers bool has(Integer) const; ///< has() only works for Maps //@}