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