OpenShot Library | libopenshot-audio 0.2.0
juce_SharedResourcePointer.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 smart-pointer that automatically creates and manages the lifetime of a
33 shared static instance of a class.
34
35 The SharedObjectType template type indicates the class to use for the shared
36 object - the only requirements on this class are that it must have a public
37 default constructor and destructor.
38
39 The SharedResourcePointer offers a pattern that differs from using a singleton or
40 static instance of an object, because it uses reference-counting to make sure that
41 the underlying shared object is automatically created/destroyed according to the
42 number of SharedResourcePointer objects that exist. When the last one is deleted,
43 the underlying object is also immediately destroyed. This allows you to use scoping
44 to manage the lifetime of a shared resource.
45
46 Note: The construction/deletion of the shared object must not involve any
47 code that makes recursive calls to a SharedResourcePointer, or you'll cause
48 a deadlock.
49
50 Example:
51 @code
52 // An example of a class that contains the shared data you want to use.
53 struct MySharedData
54 {
55 // There's no need to ever create an instance of this class directly yourself,
56 // but it does need a public constructor that does the initialisation.
57 MySharedData()
58 {
59 sharedStuff = generateHeavyweightStuff();
60 }
61
62 Array<SomeKindOfData> sharedStuff;
63 };
64
65 struct DataUserClass
66 {
67 DataUserClass()
68 {
69 // Multiple instances of the DataUserClass will all have the same
70 // shared common instance of MySharedData referenced by their sharedData
71 // member variables.
72 useSharedStuff (sharedData->sharedStuff);
73 }
74
75 // By keeping this pointer as a member variable, the shared resource
76 // is guaranteed to be available for as long as the DataUserClass object.
77 SharedResourcePointer<MySharedData> sharedData;
78 };
79
80 @endcode
81
82 @tags{Core}
83*/
84template <typename SharedObjectType>
86{
87public:
88 /** Creates an instance of the shared object.
89 If other SharedResourcePointer objects for this type already exist, then
90 this one will simply point to the same shared object that they are already
91 using. Otherwise, if this is the first SharedResourcePointer to be created,
92 then a shared object will be created automatically.
93 */
95 {
96 initialise();
97 }
98
100 {
101 initialise();
102 }
103
104 /** Destructor.
105 If no other SharedResourcePointer objects exist, this will also delete
106 the shared object to which it refers.
107 */
109 {
110 auto& holder = getSharedObjectHolder();
111 const SpinLock::ScopedLockType sl (holder.lock);
112
113 if (--(holder.refCount) == 0)
114 holder.sharedInstance = nullptr;
115 }
116
117 /** Returns the shared object. */
118 operator SharedObjectType*() const noexcept { return sharedObject; }
119
120 /** Returns the shared object. */
121 SharedObjectType& get() const noexcept { return *sharedObject; }
122
123 /** Returns the object that this pointer references.
124 The pointer returned may be a nullptr, of course.
125 */
126 SharedObjectType& getObject() const noexcept { return *sharedObject; }
127
128 /** Returns the shared object. */
129 SharedObjectType* operator->() const noexcept { return sharedObject; }
130
131 /** Returns the number of SharedResourcePointers that are currently holding the shared object. */
132 int getReferenceCount() const noexcept { return getSharedObjectHolder().refCount; }
133
134private:
135 struct SharedObjectHolder
136 {
137 SpinLock lock;
138 std::unique_ptr<SharedObjectType> sharedInstance;
139 int refCount;
140 };
141
142 static SharedObjectHolder& getSharedObjectHolder() noexcept
143 {
144 static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { nullptr };
145 return *reinterpret_cast<SharedObjectHolder*> (holder);
146 }
147
148 SharedObjectType* sharedObject;
149
150 void initialise()
151 {
152 auto& holder = getSharedObjectHolder();
153 const SpinLock::ScopedLockType sl (holder.lock);
154
155 if (++(holder.refCount) == 1)
156 holder.sharedInstance.reset (new SharedObjectType());
157
158 sharedObject = holder.sharedInstance.get();
159 }
160
161 // There's no need to assign to a SharedResourcePointer because every
162 // instance of the class is exactly the same!
163 SharedResourcePointer& operator= (const SharedResourcePointer&) = delete;
164
165 JUCE_LEAK_DETECTOR (SharedResourcePointer)
166};
167
168} // namespace juce
169
170/** @}*/
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:60
A smart-pointer that automatically creates and manages the lifetime of a shared static instance of a ...
int getReferenceCount() const noexcept
Returns the number of SharedResourcePointers that are currently holding the shared object.
SharedObjectType & getObject() const noexcept
Returns the object that this pointer references.
SharedResourcePointer()
Creates an instance of the shared object.
SharedObjectType & get() const noexcept
Returns the shared object.
SharedObjectType * operator->() const noexcept
Returns the shared object.
A simple spin-lock class that can be used as a simple, low-overhead mutex for uncontended situations.
GenericScopedLock< SpinLock > ScopedLockType
Provides the type of scoped lock to use for locking a SpinLock.