OpenShot Library | OpenShotAudio  0.2.1
juce_ReferenceCountedObject.h
1 
2 /** @weakgroup juce_core-memory
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  A base class which provides methods for reference-counting.
33 
34  To add reference-counting to a class, derive it from this class, and
35  use the ReferenceCountedObjectPtr class to point to it.
36 
37  e.g. @code
38  class MyClass : public ReferenceCountedObject
39  {
40  void foo();
41 
42  // This is a neat way of declaring a typedef for a pointer class,
43  // rather than typing out the full templated name each time..
44  using Ptr = ReferenceCountedObjectPtr<MyClass>;
45  };
46 
47  MyClass::Ptr p = new MyClass();
48  MyClass::Ptr p2 = p;
49  p = nullptr;
50  p2->foo();
51  @endcode
52 
53  Once a new ReferenceCountedObject has been assigned to a pointer, be
54  careful not to delete the object manually.
55 
56  This class uses an Atomic<int> value to hold the reference count, so
57  the reference count can be updated on multiple threads. Note that
58  whilst it's thread-safe to create and delete a ReferenceCountedObjectPtr
59  to a ReferenceCountedObject shared between threads, it's not thread-safe
60  to modify or swap the ReferenceCountedObject.
61 
62  For a faster but non-thread-safe version, use SingleThreadedReferenceCountedObject
63  instead.
64 
65  @see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject
66 
67  @tags{Core}
68 */
70 {
71 public:
72  //==============================================================================
73  /** Increments the object's reference count.
74 
75  This is done automatically by the smart pointer, but is public just
76  in case it's needed for nefarious purposes.
77  */
78  void incReferenceCount() noexcept
79  {
80  ++refCount;
81  }
82 
83  /** Decreases the object's reference count.
84  If the count gets to zero, the object will be deleted.
85  */
86  void decReferenceCount() noexcept
87  {
88  jassert (getReferenceCount() > 0);
89 
90  if (--refCount == 0)
91  delete this;
92  }
93 
94  /** Decreases the object's reference count.
95  If the count gets to zero, the object will not be deleted, but this method
96  will return true, allowing the caller to take care of deletion.
97  */
99  {
100  jassert (getReferenceCount() > 0);
101  return --refCount == 0;
102  }
103 
104  /** Returns the object's current reference count. */
105  int getReferenceCount() const noexcept { return refCount.get(); }
106 
107 
108 protected:
109  //==============================================================================
110  /** Creates the reference-counted object (with an initial ref count of zero). */
111  ReferenceCountedObject() = default;
112 
113  /** Copying from another object does not affect this one's reference-count. */
115  /** Copying from another object does not affect this one's reference-count. */
117  /** Copying from another object does not affect this one's reference-count. */
118  ReferenceCountedObject& operator= (const ReferenceCountedObject&) noexcept { return *this; }
119  /** Copying from another object does not affect this one's reference-count. */
120  ReferenceCountedObject& operator= (ReferenceCountedObject&&) noexcept { return *this; }
121 
122  /** Destructor. */
124  {
125  // it's dangerous to delete an object that's still referenced by something else!
126  jassert (getReferenceCount() == 0);
127  }
128 
129  /** Resets the reference count to zero without deleting the object.
130  You should probably never need to use this!
131  */
132  void resetReferenceCount() noexcept
133  {
134  refCount = 0;
135  }
136 
137 private:
138  //==============================================================================
139  Atomic<int> refCount { 0 };
140  friend struct ContainerDeletePolicy<ReferenceCountedObject>;
141 };
142 
143 
144 //==============================================================================
145 /**
146  Adds reference-counting to an object.
147 
148  This is effectively a version of the ReferenceCountedObject class, but which
149  uses a non-atomic counter, and so is not thread-safe (but which will be more
150  efficient).
151  For more details on how to use it, see the ReferenceCountedObject class notes.
152 
153  @see ReferenceCountedObject, ReferenceCountedObjectPtr, ReferenceCountedArray
154 
155  @tags{Core}
156 */
158 {
159 public:
160  //==============================================================================
161  /** Increments the object's reference count.
162 
163  This is done automatically by the smart pointer, but is public just
164  in case it's needed for nefarious purposes.
165  */
166  void incReferenceCount() noexcept
167  {
168  ++refCount;
169  }
170 
171  /** Decreases the object's reference count.
172  If the count gets to zero, the object will be deleted.
173  */
174  void decReferenceCount() noexcept
175  {
176  jassert (getReferenceCount() > 0);
177 
178  if (--refCount == 0)
179  delete this;
180  }
181 
182  /** Decreases the object's reference count.
183  If the count gets to zero, the object will not be deleted, but this method
184  will return true, allowing the caller to take care of deletion.
185  */
187  {
188  jassert (getReferenceCount() > 0);
189  return --refCount == 0;
190  }
191 
192  /** Returns the object's current reference count. */
193  int getReferenceCount() const noexcept { return refCount; }
194 
195 
196 protected:
197  //==============================================================================
198  /** Creates the reference-counted object (with an initial ref count of zero). */
200 
201  /** Copying from another object does not affect this one's reference-count. */
203  /** Copying from another object does not affect this one's reference-count. */
205  /** Copying from another object does not affect this one's reference-count. */
207  /** Copying from another object does not affect this one's reference-count. */
209 
210  /** Destructor. */
212  {
213  // it's dangerous to delete an object that's still referenced by something else!
214  jassert (getReferenceCount() == 0);
215  }
216 
217 private:
218  //==============================================================================
219  int refCount = 0;
220  friend struct ContainerDeletePolicy<ReferenceCountedObject>;
221 };
222 
223 
224 //==============================================================================
225 /**
226  A smart-pointer class which points to a reference-counted object.
227 
228  The template parameter specifies the class of the object you want to point to - the easiest
229  way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject
230  or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable
231  class by implementing a set of methods called incReferenceCount(), decReferenceCount(), and
232  decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods
233  should behave.
234 
235  When using this class, you'll probably want to create a typedef to abbreviate the full
236  templated name - e.g.
237  @code
238  struct MyClass : public ReferenceCountedObject
239  {
240  using Ptr = ReferenceCountedObjectPtr<MyClass>;
241  ...
242  }
243  @endcode
244 
245  @see ReferenceCountedObject, ReferenceCountedObjectArray
246 
247  @tags{Core}
248 */
249 template <class ObjectType>
251 {
252 public:
253  /** The class being referenced by this pointer. */
254  using ReferencedType = ObjectType;
255 
256  //==============================================================================
257  /** Creates a pointer to a null object. */
258  ReferenceCountedObjectPtr() = default;
259 
260  /** Creates a pointer to a null object. */
261  ReferenceCountedObjectPtr (decltype (nullptr)) noexcept {}
262 
263  /** Creates a pointer to an object.
264  This will increment the object's reference-count.
265  */
266  ReferenceCountedObjectPtr (ReferencedType* refCountedObject) noexcept
267  : referencedObject (refCountedObject)
268  {
269  incIfNotNull (refCountedObject);
270  }
271 
272  /** Creates a pointer to an object.
273  This will increment the object's reference-count.
274  */
275  ReferenceCountedObjectPtr (ReferencedType& refCountedObject) noexcept
276  : referencedObject (&refCountedObject)
277  {
278  refCountedObject.incReferenceCount();
279  }
280 
281  /** Copies another pointer.
282  This will increment the object's reference-count.
283  */
285  : referencedObject (other.referencedObject)
286  {
287  incIfNotNull (referencedObject);
288  }
289 
290  /** Takes-over the object from another pointer. */
292  : referencedObject (other.referencedObject)
293  {
294  other.referencedObject = nullptr;
295  }
296 
297  /** Copies another pointer.
298  This will increment the object's reference-count (if it is non-null).
299  */
300  template <typename Convertible>
302  : referencedObject (other.get())
303  {
304  incIfNotNull (referencedObject);
305  }
306 
307  /** Changes this pointer to point at a different object.
308  The reference count of the old object is decremented, and it might be
309  deleted if it hits zero. The new object's count is incremented.
310  */
312  {
313  return operator= (other.referencedObject);
314  }
315 
316  /** Changes this pointer to point at a different object.
317  The reference count of the old object is decremented, and it might be
318  deleted if it hits zero. The new object's count is incremented.
319  */
320  template <typename Convertible>
322  {
323  return operator= (other.get());
324  }
325 
326  /** Changes this pointer to point at a different object.
327 
328  The reference count of the old object is decremented, and it might be
329  deleted if it hits zero. The new object's count is incremented.
330  */
331  ReferenceCountedObjectPtr& operator= (ReferencedType* newObject)
332  {
333  if (newObject != nullptr)
334  return operator= (*newObject);
335 
336  reset();
337  return *this;
338  }
339 
340  /** Changes this pointer to point at a different object.
341 
342  The reference count of the old object is decremented, and it might be
343  deleted if it hits zero. The new object's count is incremented.
344  */
345  ReferenceCountedObjectPtr& operator= (ReferencedType& newObject)
346  {
347  if (referencedObject != &newObject)
348  {
349  newObject.incReferenceCount();
350  auto* oldObject = referencedObject;
351  referencedObject = &newObject;
352  decIfNotNull (oldObject);
353  }
354 
355  return *this;
356  }
357 
358  /** Resets this pointer to a null pointer. */
359  ReferenceCountedObjectPtr& operator= (decltype (nullptr))
360  {
361  reset();
362  return *this;
363  }
364 
365  /** Takes-over the object from another pointer. */
367  {
368  std::swap (referencedObject, other.referencedObject);
369  return *this;
370  }
371 
372  /** Destructor.
373  This will decrement the object's reference-count, which will cause the
374  object to be deleted when the ref-count hits zero.
375  */
377  {
378  decIfNotNull (referencedObject);
379  }
380 
381  //==============================================================================
382  /** Returns the object that this pointer references.
383  The pointer returned may be null, of course.
384  */
385  ReferencedType* get() const noexcept { return referencedObject; }
386 
387  /** Resets this object to a null pointer. */
388  void reset() noexcept
389  {
390  auto oldObject = referencedObject; // need to null the pointer before deleting the object
391  referencedObject = nullptr; // in case this ptr is itself deleted as a side-effect
392  decIfNotNull (oldObject); // of the destructor
393  }
394 
395  // the -> operator is called on the referenced object
396  ReferencedType* operator->() const noexcept
397  {
398  jassert (referencedObject != nullptr); // null pointer method call!
399  return referencedObject;
400  }
401 
402  /** Dereferences the object that this pointer references.
403  The pointer returned may be null, of course.
404  */
405  ReferencedType& operator*() const noexcept { jassert (referencedObject != nullptr); return *referencedObject; }
406 
407  /** Checks whether this pointer is null */
408  bool operator== (decltype (nullptr)) const noexcept { return referencedObject == nullptr; }
409  /** Checks whether this pointer is null */
410  bool operator!= (decltype (nullptr)) const noexcept { return referencedObject != nullptr; }
411 
412  /** Compares two ReferenceCountedObjectPtrs. */
413  bool operator== (const ObjectType* other) const noexcept { return referencedObject == other; }
414  /** Compares two ReferenceCountedObjectPtrs. */
415  bool operator== (const ReferenceCountedObjectPtr& other) const noexcept { return referencedObject == other.get(); }
416  /** Compares two ReferenceCountedObjectPtrs. */
417  bool operator!= (const ObjectType* other) const noexcept { return referencedObject != other; }
418  /** Compares two ReferenceCountedObjectPtrs. */
419  bool operator!= (const ReferenceCountedObjectPtr& other) const noexcept { return referencedObject != other.get(); }
420 
421  #if JUCE_STRICT_REFCOUNTEDPOINTER
422  /** Checks whether this pointer is null */
423  explicit operator bool() const noexcept { return referencedObject != nullptr; }
424 
425  #else
426  /** Returns the object that this pointer references.
427  The pointer returned may be null, of course.
428  Note that this methods allows the compiler to be very lenient with what it allows you to do
429  with the pointer, it's safer to disable this by setting JUCE_STRICT_REFCOUNTEDPOINTER=1, which
430  increased type safety and can prevent some common slip-ups.
431  */
432  operator ReferencedType*() const noexcept { return referencedObject; }
433  #endif
434 
435 
436  // This old method is deprecated in favour of the shorter and more standard get() method.
437  JUCE_DEPRECATED_WITH_BODY (ReferencedType* getObject() const, { return get(); })
438 
439 private:
440  //==============================================================================
441  ReferencedType* referencedObject = nullptr;
442 
443  static void incIfNotNull (ReferencedType* o) noexcept
444  {
445  if (o != nullptr)
446  o->incReferenceCount();
447  }
448 
449  static void decIfNotNull (ReferencedType* o) noexcept
450  {
451  if (o != nullptr && o->decReferenceCountWithoutDeleting())
453  }
454 };
455 
456 
457 //==============================================================================
458 /** Compares two ReferenceCountedObjectPtrs. */
459 template <typename Type>
460 bool operator== (const Type* object1, const ReferenceCountedObjectPtr<Type>& object2) noexcept
461 {
462  return object1 == object2.get();
463 }
464 
465 /** Compares two ReferenceCountedObjectPtrs. */
466 template <typename Type>
467 bool operator!= (const Type* object1, const ReferenceCountedObjectPtr<Type>& object2) noexcept
468 {
469  return object1 != object2.get();
470 }
471 
472 } // namespace juce
473 
474 /** @}*/
#define JUCE_API
This macro is added to all JUCE public class declarations.
bool decReferenceCountWithoutDeleting() noexcept
Decreases the object&#39;s reference count.
ReferenceCountedObjectPtr(ReferenceCountedObjectPtr &&other) noexcept
Takes-over the object from another pointer.
void decReferenceCount() noexcept
Decreases the object&#39;s reference count.
int getReferenceCount() const noexcept
Returns the object&#39;s current reference count.
ReferenceCountedObjectPtr(const ReferenceCountedObjectPtr &other) noexcept
Copies another pointer.
void reset() noexcept
Resets this object to a null pointer.
void decReferenceCount() noexcept
Decreases the object&#39;s reference count.
void incReferenceCount() noexcept
Increments the object&#39;s reference count.
ReferenceCountedObject(ReferenceCountedObject &&) noexcept
Copying from another object does not affect this one&#39;s reference-count.
int getReferenceCount() const noexcept
Returns the object&#39;s current reference count.
SingleThreadedReferenceCountedObject(const SingleThreadedReferenceCountedObject &)
Copying from another object does not affect this one&#39;s reference-count.
void incReferenceCount() noexcept
Increments the object&#39;s reference count.
ReferencedType & operator*() const noexcept
Dereferences the object that this pointer references.
void resetReferenceCount() noexcept
Resets the reference count to zero without deleting the object.
SingleThreadedReferenceCountedObject(SingleThreadedReferenceCountedObject &&)
Copying from another object does not affect this one&#39;s reference-count.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
Used by container classes as an indirect way to delete an object of a particular type.
Adds reference-counting to an object.
ReferenceCountedObjectPtr(decltype(nullptr)) noexcept
Creates a pointer to a null object.
A smart-pointer class which points to a reference-counted object.
ReferenceCountedObjectPtr(ReferencedType *refCountedObject) noexcept
Creates a pointer to an object.
A base class which provides methods for reference-counting.
bool decReferenceCountWithoutDeleting() noexcept
Decreases the object&#39;s reference count.
ReferenceCountedObject(const ReferenceCountedObject &) noexcept
Copying from another object does not affect this one&#39;s reference-count.
ReferenceCountedObjectPtr(const ReferenceCountedObjectPtr< Convertible > &other) noexcept
Copies another pointer.
ReferenceCountedObjectPtr(ReferencedType &refCountedObject) noexcept
Creates a pointer to an object.