OpenShot Library | OpenShotAudio 0.2.2
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
27namespace 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{
71public:
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
108protected:
109 //==============================================================================
110 /** Creates the reference-counted object (with an initial ref count of zero). */
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
137private:
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{
159public:
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
196protected:
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
217private:
218 //==============================================================================
219 int refCount = 0;
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*/
249template <class ObjectType>
251{
252public:
253 /** The class being referenced by this pointer. */
254 using ReferencedType = ObjectType;
255
256 //==============================================================================
257 /** Creates a pointer to a null object. */
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 */
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 */
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. */
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
439private:
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())
452 ContainerDeletePolicy<ReferencedType>::destroy (o);
453 }
454};
455
456
457//==============================================================================
458/** Compares two ReferenceCountedObjectPtrs. */
459template <typename Type>
460bool operator== (const Type* object1, const ReferenceCountedObjectPtr<Type>& object2) noexcept
461{
462 return object1 == object2.get();
463}
464
465/** Compares two ReferenceCountedObjectPtrs. */
466template <typename Type>
467bool operator!= (const Type* object1, const ReferenceCountedObjectPtr<Type>& object2) noexcept
468{
469 return object1 != object2.get();
470}
471
472} // namespace juce
473
474/** @}*/
A smart-pointer class which points to a reference-counted object.
ReferenceCountedObjectPtr & operator=(const ReferenceCountedObjectPtr &other)
Changes this pointer to point at a different object.
ObjectType ReferencedType
The class being referenced by this pointer.
bool operator!=(decltype(nullptr)) const noexcept
Checks whether this pointer is null.
ReferenceCountedObjectPtr(ReferenceCountedObjectPtr &&other) noexcept
Takes-over the object from another pointer.
bool operator==(decltype(nullptr)) const noexcept
Checks whether this pointer is null.
ReferenceCountedObjectPtr(ReferencedType *refCountedObject) noexcept
Creates a pointer to an object.
ReferenceCountedObjectPtr(ReferencedType &refCountedObject) noexcept
Creates a pointer to an object.
ReferenceCountedObjectPtr()=default
Creates a pointer to a null object.
ReferenceCountedObjectPtr(const ReferenceCountedObjectPtr< Convertible > &other) noexcept
Copies another pointer.
void reset() noexcept
Resets this object to a null pointer.
ReferenceCountedObjectPtr(decltype(nullptr)) noexcept
Creates a pointer to a null object.
ReferencedType & operator*() const noexcept
Dereferences the object that this pointer references.
ReferenceCountedObjectPtr(const ReferenceCountedObjectPtr &other) noexcept
Copies another pointer.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
A base class which provides methods for reference-counting.
ReferenceCountedObject(const ReferenceCountedObject &) noexcept
Copying from another object does not affect this one's reference-count.
ReferenceCountedObject(ReferenceCountedObject &&) noexcept
Copying from another object does not affect this one's reference-count.
void resetReferenceCount() noexcept
Resets the reference count to zero without deleting the object.
bool decReferenceCountWithoutDeleting() noexcept
Decreases the object's reference count.
ReferenceCountedObject()=default
Creates the reference-counted object (with an initial ref count of zero).
void incReferenceCount() noexcept
Increments the object's reference count.
int getReferenceCount() const noexcept
Returns the object's current reference count.
void decReferenceCount() noexcept
Decreases the object's reference count.
SingleThreadedReferenceCountedObject(SingleThreadedReferenceCountedObject &&)
Copying from another object does not affect this one's reference-count.
SingleThreadedReferenceCountedObject(const SingleThreadedReferenceCountedObject &)
Copying from another object does not affect this one's reference-count.
SingleThreadedReferenceCountedObject()=default
Creates the reference-counted object (with an initial ref count of zero).
void decReferenceCount() noexcept
Decreases the object's reference count.
void incReferenceCount() noexcept
Increments the object's reference count.
int getReferenceCount() const noexcept
Returns the object's current reference count.
bool decReferenceCountWithoutDeleting() noexcept
Decreases the object's reference count.
#define JUCE_API
This macro is added to all JUCE public class declarations.
Used by container classes as an indirect way to delete an object of a particular type.