1 /* 2 ============================================================================== 3 4 This file is part of the JUCE library. 5 Copyright (c) 2020 - Raw Material Software Limited 6 7 JUCE is an open source library subject to commercial or open-source 8 licensing. 9 10 The code included in this file is provided under the terms of the ISC license 11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission 12 To use, copy, modify, and/or distribute this software for any purpose with or 13 without fee is hereby granted provided that the above copyright notice and 14 this permission notice appear in all copies. 15 16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 18 DISCLAIMED. 19 20 ============================================================================== 21 */ 22 23 namespace juce 24 { 25 26 //============================================================================== 27 /** 28 This class acts as a pointer which will automatically become null if the object 29 to which it points is deleted. 30 31 To accomplish this, the source object needs to cooperate by performing a couple of simple tasks. 32 It must embed a WeakReference::Master object, which stores a shared pointer object, and must clear 33 this master pointer in its destructor. 34 35 Note that WeakReference is not designed to be thread-safe, so if you're accessing it from 36 different threads, you'll need to do your own locking around all uses of the pointer and 37 the object it refers to. 38 39 E.g. 40 @code 41 class MyObject 42 { 43 public: 44 MyObject() {} 45 46 ~MyObject() 47 { 48 // This will zero all the references - you need to call this in your destructor. 49 masterReference.clear(); 50 } 51 52 private: 53 // You need to embed a variable of this type, with the name "masterReference" inside your object. If the 54 // variable is not public, you should make your class a friend of WeakReference<MyObject> so that the 55 // WeakReference class can access it. 56 WeakReference<MyObject>::Master masterReference; 57 friend class WeakReference<MyObject>; 58 }; 59 60 OR: just use the handy JUCE_DECLARE_WEAK_REFERENCEABLE macro to do all this for you. 61 62 // Here's an example of using a pointer.. 63 64 auto* n = new MyObject(); 65 WeakReference<MyObject> myObjectRef = n; 66 67 auto pointer1 = myObjectRef.get(); // returns a valid pointer to 'n' 68 delete n; 69 auto pointer2 = myObjectRef.get(); // now returns nullptr 70 @endcode 71 72 @see WeakReference::Master 73 74 @tags{Core} 75 */ 76 template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject> 77 class WeakReference 78 { 79 public: 80 /** Creates a null WeakReference. */ 81 inline WeakReference() = default; 82 83 /** Creates a WeakReference that points at the given object. */ WeakReference(ObjectType * object)84 WeakReference (ObjectType* object) : holder (getRef (object)) {} 85 86 /** Creates a copy of another WeakReference. */ WeakReference(const WeakReference & other)87 WeakReference (const WeakReference& other) noexcept : holder (other.holder) {} 88 89 /** Move constructor */ WeakReference(WeakReference && other)90 WeakReference (WeakReference&& other) noexcept : holder (std::move (other.holder)) {} 91 92 /** Copies another pointer to this one. */ 93 WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; } 94 95 /** Copies another pointer to this one. */ 96 WeakReference& operator= (ObjectType* newObject) { holder = getRef (newObject); return *this; } 97 98 /** Move assignment operator */ 99 WeakReference& operator= (WeakReference&& other) noexcept { holder = std::move (other.holder); return *this; } 100 101 /** Returns the object that this pointer refers to, or null if the object no longer exists. */ get()102 ObjectType* get() const noexcept { return holder != nullptr ? holder->get() : nullptr; } 103 104 /** Returns the object that this pointer refers to, or null if the object no longer exists. */ 105 operator ObjectType*() const noexcept { return get(); } 106 107 /** Returns the object that this pointer refers to, or null if the object no longer exists. */ 108 ObjectType* operator->() const noexcept { return get(); } 109 110 /** This returns true if this reference has been pointing at an object, but that object has 111 since been deleted. 112 113 If this reference was only ever pointing at a null pointer, this will return false. Using 114 operator=() to make this refer to a different object will reset this flag to match the status 115 of the reference from which you're copying. 116 */ wasObjectDeleted()117 bool wasObjectDeleted() const noexcept { return holder != nullptr && holder->get() == nullptr; } 118 119 bool operator== (ObjectType* object) const noexcept { return get() == object; } 120 bool operator!= (ObjectType* object) const noexcept { return get() != object; } 121 122 //============================================================================== 123 /** This class is used internally by the WeakReference class - don't use it directly 124 in your code! 125 @see WeakReference 126 */ 127 class SharedPointer : public ReferenceCountingType 128 { 129 public: SharedPointer(ObjectType * obj)130 explicit SharedPointer (ObjectType* obj) noexcept : owner (obj) {} 131 get()132 inline ObjectType* get() const noexcept { return owner; } clearPointer()133 void clearPointer() noexcept { owner = nullptr; } 134 135 private: 136 ObjectType* owner; 137 138 JUCE_DECLARE_NON_COPYABLE (SharedPointer) 139 }; 140 141 using SharedRef = ReferenceCountedObjectPtr<SharedPointer>; 142 143 //============================================================================== 144 /** 145 This class is embedded inside an object to which you want to attach WeakReference pointers. 146 See the WeakReference class notes for an example of how to use this class. 147 @see WeakReference 148 */ 149 class Master 150 { 151 public: 152 Master() = default; 153 ~Master()154 ~Master() noexcept 155 { 156 // You must remember to call clear() in your source object's destructor! See the notes 157 // for the WeakReference class for an example of how to do this. 158 jassert (sharedPointer == nullptr || sharedPointer->get() == nullptr); 159 } 160 161 /** The first call to this method will create an internal object that is shared by all weak 162 references to the object. 163 */ getSharedPointer(ObjectType * object)164 SharedRef getSharedPointer (ObjectType* object) 165 { 166 if (sharedPointer == nullptr) 167 { 168 sharedPointer = *new SharedPointer (object); 169 } 170 else 171 { 172 // You're trying to create a weak reference to an object that has already been deleted!! 173 jassert (sharedPointer->get() != nullptr); 174 } 175 176 return sharedPointer; 177 } 178 179 /** The object that owns this master pointer should call this before it gets destroyed, 180 to zero all the references to this object that may be out there. See the WeakReference 181 class notes for an example of how to do this. 182 */ clear()183 void clear() noexcept 184 { 185 if (sharedPointer != nullptr) 186 sharedPointer->clearPointer(); 187 } 188 189 /** Returns the number of WeakReferences that are out there pointing to this object. */ getNumActiveWeakReferences()190 int getNumActiveWeakReferences() const noexcept 191 { 192 return sharedPointer == nullptr ? 0 : (sharedPointer->getReferenceCount() - 1); 193 } 194 195 private: 196 SharedRef sharedPointer; 197 198 JUCE_DECLARE_NON_COPYABLE (Master) 199 }; 200 201 private: 202 SharedRef holder; 203 getRef(ObjectType * o)204 static SharedRef getRef (ObjectType* o) 205 { 206 if (o != nullptr) 207 return o->masterReference.getSharedPointer (o); 208 209 return {}; 210 } 211 }; 212 213 214 //============================================================================== 215 /** 216 Macro to easily allow a class to be made weak-referenceable. 217 This can be inserted in a class definition to add the requisite weak-ref boilerplate to that class. 218 e.g. 219 220 @code 221 class MyObject 222 { 223 public: 224 MyObject(); 225 ~MyObject(); 226 227 private: 228 JUCE_DECLARE_WEAK_REFERENCEABLE (MyObject) 229 }; 230 @endcode 231 232 @see WeakReference, WeakReference::Master 233 */ 234 #define JUCE_DECLARE_WEAK_REFERENCEABLE(Class) \ 235 struct WeakRefMaster : public juce::WeakReference<Class>::Master { ~WeakRefMaster() { this->clear(); } }; \ 236 WeakRefMaster masterReference; \ 237 friend class juce::WeakReference<Class>; \ 238 239 240 } // namespace juce 241