From 5c50ee4f94dca384b1185ece3a0c0116e3ba9de8 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 21 Oct 2021 18:56:26 +0100 Subject: [PATCH] MouseCursor: Simplify implementation using shared_ptr instead of manual refcounting --- .../mouse/juce_MouseCursor.cpp | 124 +++++------------- .../juce_gui_basics/mouse/juce_MouseCursor.h | 3 +- 2 files changed, 35 insertions(+), 92 deletions(-) diff --git a/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp b/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp index 88ed9ae440..54b04efdc0 100644 --- a/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp +++ b/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp @@ -45,96 +45,65 @@ class MouseCursor::SharedCursorHandle { public: explicit SharedCursorHandle (const MouseCursor::StandardCursorType type) - : handle (createStandardMouseCursor (type)), - standardType (type), - isStandard (true) + : handle (createStandardMouseCursor (type), Deleter { true }), + standardType (type) { } SharedCursorHandle (const Image& image, Point hotSpot, float scaleFactor) - : info (new CustomMouseCursorInfo (image, hotSpot, scaleFactor)), - handle (info->create()), - standardType (MouseCursor::NormalCursor), - isStandard (false) + : info (std::make_unique (image, hotSpot, scaleFactor)), + handle (info->create(), Deleter { false }), + standardType (MouseCursor::NormalCursor) { // your hotspot needs to be within the bounds of the image! jassert (image.getBounds().contains (hotSpot)); } - ~SharedCursorHandle() + static std::shared_ptr createStandard (const MouseCursor::StandardCursorType type) { - deleteMouseCursor (handle, isStandard); - } - - static SharedCursorHandle* createStandard (const MouseCursor::StandardCursorType type) - { - jassert (isPositiveAndBelow (type, MouseCursor::NumStandardCursorTypes)); + if (! isPositiveAndBelow (type, MouseCursor::NumStandardCursorTypes)) + return nullptr; - const SpinLock::ScopedLockType sl (lock); - auto& c = getSharedCursor (type); + static SpinLock mutex; + static std::array, MouseCursor::NumStandardCursorTypes> cursors; - if (c == nullptr) - c = new SharedCursorHandle (type); - else - c->retain(); + const SpinLock::ScopedLockType sl (mutex); - return c; - } + auto& weak = cursors[type]; - bool isStandardType (MouseCursor::StandardCursorType type) const noexcept - { - return type == standardType && isStandard; - } + if (auto strong = weak.lock()) + return strong; - SharedCursorHandle* retain() noexcept - { - ++refCount; - return this; + auto strong = std::make_shared (type); + weak = strong; + return strong; } - void release() + bool isStandardType (MouseCursor::StandardCursorType type) const noexcept { - if (--refCount == 0) - { - if (isStandard) - { - const SpinLock::ScopedLockType sl (lock); - getSharedCursor (standardType) = nullptr; - } - - delete this; - } + return type == standardType && handle.get_deleter().isStandard; } - void* getHandle() const noexcept { return handle; } - void setHandle (void* newHandle) { handle = newHandle; } - + void* getHandle() const noexcept { return handle.get(); } MouseCursor::StandardCursorType getType() const noexcept { return standardType; } CustomMouseCursorInfo* getCustomInfo() const noexcept { return info.get(); } private: + struct Deleter + { + void operator() (void* ptr) const noexcept { deleteMouseCursor (ptr, isStandard); } + const bool isStandard; + }; + std::unique_ptr info; - void* handle; - Atomic refCount { 1 }; + std::unique_ptr handle; const MouseCursor::StandardCursorType standardType; - const bool isStandard; - static SpinLock lock; - - static SharedCursorHandle*& getSharedCursor (const MouseCursor::StandardCursorType type) - { - static SharedCursorHandle* cursors[MouseCursor::NumStandardCursorTypes] = {}; - return cursors[type]; - } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedCursorHandle) }; -SpinLock MouseCursor::SharedCursorHandle::lock; - //============================================================================== -MouseCursor::MouseCursor() noexcept -{ -} +MouseCursor::MouseCursor() noexcept = default; MouseCursor::MouseCursor (const StandardCursorType type) : cursorHandle (type != MouseCursor::NormalCursor ? SharedCursorHandle::createStandard (type) : nullptr) @@ -147,44 +116,19 @@ MouseCursor::MouseCursor (const Image& image, int hotSpotX, int hotSpotY) } MouseCursor::MouseCursor (const Image& image, int hotSpotX, int hotSpotY, float scaleFactor) - : cursorHandle (new SharedCursorHandle (image, { hotSpotX, hotSpotY }, scaleFactor)) + : cursorHandle (std::make_shared (image, Point { hotSpotX, hotSpotY }, scaleFactor)) { } -MouseCursor::MouseCursor (const MouseCursor& other) - : cursorHandle (other.cursorHandle == nullptr ? nullptr : other.cursorHandle->retain()) -{ -} +MouseCursor::MouseCursor (const MouseCursor&) = default; -MouseCursor::~MouseCursor() -{ - if (cursorHandle != nullptr) - cursorHandle->release(); -} +MouseCursor::~MouseCursor() = default; -MouseCursor& MouseCursor::operator= (const MouseCursor& other) -{ - if (other.cursorHandle != nullptr) - other.cursorHandle->retain(); +MouseCursor& MouseCursor::operator= (const MouseCursor&) = default; - if (cursorHandle != nullptr) - cursorHandle->release(); +MouseCursor::MouseCursor (MouseCursor&&) noexcept = default; - cursorHandle = other.cursorHandle; - return *this; -} - -MouseCursor::MouseCursor (MouseCursor&& other) noexcept - : cursorHandle (other.cursorHandle) -{ - other.cursorHandle = nullptr; -} - -MouseCursor& MouseCursor::operator= (MouseCursor&& other) noexcept -{ - std::swap (cursorHandle, other.cursorHandle); - return *this; -} +MouseCursor& MouseCursor::operator= (MouseCursor&&) noexcept = default; bool MouseCursor::operator== (const MouseCursor& other) const noexcept { diff --git a/modules/juce_gui_basics/mouse/juce_MouseCursor.h b/modules/juce_gui_basics/mouse/juce_MouseCursor.h index 9f48cef6cc..c6996b5d53 100644 --- a/modules/juce_gui_basics/mouse/juce_MouseCursor.h +++ b/modules/juce_gui_basics/mouse/juce_MouseCursor.h @@ -166,8 +166,7 @@ public: private: //============================================================================== class SharedCursorHandle; - friend class SharedCursorHandle; - SharedCursorHandle* cursorHandle = nullptr; + std::shared_ptr cursorHandle; friend class MouseInputSourceInternal; void showInWindow (ComponentPeer*) const;