JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
fobject.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------
2// Flags : clang-format SMTGSequencer
3// Project : SDK Base
4// Version : 1.0
5//
6// Category : Helpers
7// Filename : base/source/fobject.cpp
8// Created by : Steinberg, 2008
9// Description : Basic Object implementing FUnknown
10//
11//-----------------------------------------------------------------------------
12// LICENSE
13// (c) 2023, Steinberg Media Technologies GmbH, All Rights Reserved
14//-----------------------------------------------------------------------------
15// Redistribution and use in source and binary forms, with or without modification,
16// are permitted provided that the following conditions are met:
17//
18// * Redistributions of source code must retain the above copyright notice,
19// this list of conditions and the following disclaimer.
20// * Redistributions in binary form must reproduce the above copyright notice,
21// this list of conditions and the following disclaimer in the documentation
22// and/or other materials provided with the distribution.
23// * Neither the name of the Steinberg Media Technologies nor the names of its
24// contributors may be used to endorse or promote products derived from this
25// software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
35// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
36// OF THE POSSIBILITY OF SUCH DAMAGE.
37//-----------------------------------------------------------------------------
38
39#include "base/source/fobject.h"
41
42#include <vector>
43#define SMTG_VALIDATE_DEPENDENCY_COUNT DEVELOPMENT // validating dependencyCount
44
45#if SMTG_DEPENDENCY_COUNT
47#define SMTG_DEPENDENCY_CHECK_LEVEL 1 // 1 => minimal assert, 2 => full assert
48#endif // SMTG_DEPENDENCY_COUNT
49
50namespace Steinberg {
51
52IUpdateHandler* FObject::gUpdateHandler = nullptr;
53
54//------------------------------------------------------------------------
55const FUID FObject::iid;
56
57//------------------------------------------------------------------------
59{
60 // the object iid is always generated so that different components
61 // only can cast to their own objects
62 // this initializer must be after the definition of FObject::iid, otherwise
63 // the default constructor of FUID will clear the generated iid
64 FObjectIIDInitializer () { const_cast<FUID&> (FObject::iid).generate (); }
65} gFObjectIidInitializer;
66
67//------------------------------------------------------------------------
69{
70#if SMTG_DEPENDENCY_COUNT && DEVELOPMENT
71 static bool localNeverDebugger = false;
72#endif
73
74#if DEVELOPMENT
75 if (refCount > 1)
76 FDebugPrint ("Refcount is %d when trying to delete %s\n", refCount, isA ());
77#endif
78
79#if SMTG_DEPENDENCY_COUNT
80#if SMTG_DEPENDENCY_CHECK_LEVEL >= 1
81 if (gUpdateHandler)
82 {
83#if DEVELOPMENT
84 SMTG_ASSERT (dependencyCount == 0 || localNeverDebugger);
85#endif // DEVELOPMENT
86 }
87#endif
88#endif // SMTG_DEPENDENCY_COUNT
89
90#if SMTG_VALIDATE_DEPENDENCY_COUNT
91 if (!gUpdateHandler || gUpdateHandler != UpdateHandler::instance (false))
92 return;
93
94 auto updateHandler = UpdateHandler::instance ();
95 if (!updateHandler || updateHandler == this)
96 return;
97
98 SMTG_ASSERT ((updateHandler->checkDeferred (this) == false || localNeverDebugger) &&
99 "'this' has scheduled a deferUpdate that was not yet delivered");
100
101 if (updateHandler->hasDependencies (this))
102 {
104 (false || localNeverDebugger) &&
105 "Another object is still dependent on 'this'. This leads to zombie entries in the dependency map that can later crash.");
106 FDebugPrint ("Object still has dependencies %x %s\n", this, this->isA ());
107 updateHandler->printForObject (this);
108 }
109#endif // SMTG_VALIDATE_DEPENDENCY_COUNT
110}
111
112//------------------------------------------------------------------------
113uint32 PLUGIN_API FObject::addRef ()
114{
115 return FUnknownPrivate::atomicAdd (refCount, 1);
117
118//------------------------------------------------------------------------
119uint32 PLUGIN_API FObject::release ()
120{
121 if (FUnknownPrivate::atomicAdd (refCount, -1) == 0)
122 {
123 refCount = -1000;
124 delete this;
125 return 0;
126 }
127 return refCount;
128}
129
130//------------------------------------------------------------------------
131tresult PLUGIN_API FObject::queryInterface (const TUID _iid, void** obj)
132{
133 QUERY_INTERFACE (_iid, obj, FUnknown::iid, FUnknown)
134 QUERY_INTERFACE (_iid, obj, IDependent::iid, IDependent)
135 QUERY_INTERFACE (_iid, obj, FObject::iid, FObject)
136 *obj = nullptr;
137 return kNoInterface;
138}
139
140//------------------------------------------------------------------------
142{
143 if (!gUpdateHandler)
144 return;
145
146 gUpdateHandler->addDependent (unknownCast (), dep);
147#if SMTG_DEPENDENCY_COUNT
148 dependencyCount++;
149#endif
150}
151
152//------------------------------------------------------------------------
154{
155#if SMTG_DEPENDENCY_COUNT && DEVELOPMENT
156 static bool localNeverDebugger = false;
157#endif
158
159 if (!gUpdateHandler)
160 return;
161
162#if SMTG_DEPENDENCY_COUNT
163 if (gUpdateHandler != UpdateHandler::instance (false))
164 {
165 gUpdateHandler->removeDependent (unknownCast (), dep);
166 dependencyCount--;
167 return;
168 }
169#if SMTG_DEPENDENCY_CHECK_LEVEL > 1
170 SMTG_ASSERT ((dependencyCount > 0 || localNeverDebugger) &&
171 "All dependencies have already been removed - mmichaelis 7/2021");
172#endif
173 size_t removeCount;
174 UpdateHandler::instance ()->removeDependent (unknownCast (), dep, removeCount);
175 if (removeCount == 0)
176 {
177#if SMTG_DEPENDENCY_CHECK_LEVEL > 1
178 SMTG_ASSERT (localNeverDebugger && "No dependency to remove - ygrabit 8/2021");
179#endif
180 }
181 else
182 {
183 SMTG_ASSERT ((removeCount == 1 || localNeverDebugger) &&
184 "Duplicated dependencies established - mmichaelis 7/2021");
185 }
186 dependencyCount -= (int16)removeCount;
187#else
188 gUpdateHandler->removeDependent (unknownCast (), dep);
189#endif // SMTG_DEPENDENCY_COUNT
190}
191
192//------------------------------------------------------------------------
193void FObject::changed (int32 msg)
194{
195 if (gUpdateHandler)
196 gUpdateHandler->triggerUpdates (unknownCast (), msg);
197 else
198 updateDone (msg);
199}
200
201//------------------------------------------------------------------------
202void FObject::deferUpdate (int32 msg)
203{
204 if (gUpdateHandler)
205 gUpdateHandler->deferUpdates (unknownCast (), msg);
206 else
207 updateDone (msg);
208}
209
210//------------------------------------------------------------------------
212//------------------------------------------------------------------------
213namespace Singleton {
215ObjectVector* singletonInstances = nullptr;
216bool singletonsTerminated = false;
217Steinberg::Base::Thread::FLock* singletonsLock;
218
220{
221 return singletonsTerminated;
222}
223
225{
226 if (!singletonsLock) // assume first call not from multiple threads
227 singletonsLock = NEW Steinberg::Base::Thread::FLock;
228 singletonsLock->lock ();
229}
230
231void unlockRegister ()
232{
233 singletonsLock->unlock ();
234}
235
237{
238 SMTG_ASSERT (singletonsTerminated == false)
239 if (singletonsTerminated == false)
240 {
241 if (singletonInstances == nullptr)
242 singletonInstances = NEW std::vector<FObject**>;
243 singletonInstances->push_back (o);
244 }
245}
246
248{
249 ~Deleter ()
250 {
251 singletonsTerminated = true;
252 if (singletonInstances)
253 {
254 for (Steinberg::FObject** obj : *singletonInstances)
255 {
256 (*obj)->release ();
257 *obj = nullptr;
258 obj = nullptr;
259 }
260
261 delete singletonInstances;
262 singletonInstances = nullptr;
263 }
264 delete singletonsLock;
265 singletonsLock = nullptr;
266 }
267} deleter;
268}
269
270//------------------------------------------------------------------------
271} // namespace Steinberg
FLock declaration.
Definition flock.h:92
void unlock() SMTG_OVERRIDE
Disables lock.
Definition flock.cpp:114
void lock() SMTG_OVERRIDE
Enables lock.
Definition flock.cpp:98
Implements FUnknown and IDependent.
Definition fobject.h:84
virtual void addDependent(IDependent *dep)
adds dependency to the object
Definition fobject.cpp:141
virtual void removeDependent(IDependent *dep)
removes dependency from the object
Definition fobject.cpp:153
virtual void changed(int32 msg=kChanged)
Inform all dependents, that the object has changed.
Definition fobject.cpp:193
static const FUID iid
Special UID that is used to cast an FUnknown pointer to a FObject.
Definition fobject.h:130
uint32 PLUGIN_API addRef() SMTG_OVERRIDE
please refer to FUnknown::addref ()
Definition fobject.cpp:113
virtual void deferUpdate(int32 msg=kChanged)
Similar to triggerUpdates, except only delivered in idle (usefull in collecting updates).
Definition fobject.cpp:202
virtual ~FObject()
destructor...
Definition fobject.cpp:68
tresult PLUGIN_API queryInterface(const TUID _iid, void **obj) SMTG_OVERRIDE
please refer to FUnknown::queryInterface ()
Definition fobject.cpp:131
virtual void updateDone(int32)
empty virtual method that should be overridden by derived classes
Definition fobject.h:119
int32 refCount
COM-model local reference count.
Definition fobject.h:134
uint32 PLUGIN_API release() SMTG_OVERRIDE
please refer to FUnknown::release ()
Definition fobject.cpp:119
virtual FClassID isA() const
a local alternative to getFClassID ()
Definition fobject.h:99
FUnknown * unknownCast()
get FUnknown interface from object
Definition fobject.h:104
Handling 16 Byte Globally Unique Identifiers.
Definition funknown.h:241
The basic interface of all interfaces.
Definition funknown.h:375
A dependent will get notified about changes of a model.
virtual tresult PLUGIN_API deferUpdates(FUnknown *object, int32 message)=0
Same as triggerUpdates, but delivered in idle (usefull to collect updates).
virtual tresult PLUGIN_API removeDependent(FUnknown *object, IDependent *dependent)=0
Remove a previously installed dependency.
virtual tresult PLUGIN_API triggerUpdates(FUnknown *object, int32 message)=0
Inform all dependents, that object has changed.
virtual tresult PLUGIN_API addDependent(FUnknown *object, IDependent *dependent)=0
Install update notification for given object.
#define SMTG_ASSERT(f)
if DEVELOPMENT is not set, these macros will do nothing.
Definition fdebug.h:200
Locks.
Basic Object implementing FUnknown.
bool isTerminated()
Returns true when singleton instances were already released.
Definition fobject.cpp:219
void lockRegister()
lock and unlock the singleton registration for multi-threading safety
Definition fobject.cpp:224
void registerInstance(FObject **o)
registers an instance (type FObject)
Definition fobject.cpp:236
T push_back(T... args)