OpenShot Audio Library | OpenShotAudio  0.6.0
juce_Singleton.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - 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 //==============================================================================
37 template <typename Type, typename MutexType, bool onlyCreateOncePerRun>
38 struct SingletonHolder : private MutexType // (inherited so we can use the empty-base-class optimisation)
39 {
40  SingletonHolder() = default;
41 
43  {
44  /* The static singleton holder is being deleted before the object that it holds
45  has been deleted. This could mean that you've forgotten to call clearSingletonInstance()
46  in the class's destructor, or have failed to delete it before your app shuts down.
47  If you're having trouble cleaning up your singletons, perhaps consider using the
48  SharedResourcePointer class instead.
49  */
50  jassert (instance.load() == nullptr);
51  }
52 
54  Type* get()
55  {
56  if (auto* ptr = instance.load())
57  return ptr;
58 
59  typename MutexType::ScopedLockType sl (*this);
60 
61  if (auto* ptr = instance.load())
62  return ptr;
63 
64  auto once = onlyCreateOncePerRun; // (local copy avoids VS compiler warning about this being constant)
65 
66  if (once)
67  {
68  static bool createdOnceAlready = false;
69 
70  if (createdOnceAlready)
71  {
72  // This means that the doNotRecreateAfterDeletion flag was set
73  // and you tried to create the singleton more than once.
74  jassertfalse;
75  return nullptr;
76  }
77 
78  createdOnceAlready = true;
79  }
80 
81  static bool alreadyInside = false;
82 
83  if (alreadyInside)
84  {
85  // This means that your object's constructor has done something which has
86  // ended up causing a recursive loop of singleton creation.
87  jassertfalse;
88  return nullptr;
89  }
90 
91  const ScopedValueSetter<bool> scope (alreadyInside, true);
92  return getWithoutChecking();
93  }
94 
99  {
100  if (auto* p = instance.load())
101  return p;
102 
103  auto* newObject = new Type(); // (create into a local so that instance is still null during construction)
104  instance.store (newObject);
105  return newObject;
106  }
107 
110  {
111  typename MutexType::ScopedLockType sl (*this);
112  delete instance.exchange (nullptr);
113  }
114 
116  void clear (Type* expectedObject) noexcept
117  {
118  instance.compare_exchange_strong (expectedObject, nullptr);
119  }
120 
121  // This must be atomic, otherwise a late call to get() may attempt to read instance while it is
122  // being modified by the very first call to get().
123  std::atomic<Type*> instance { nullptr };
124 };
125 
126 
127 //==============================================================================
184 #define JUCE_DECLARE_SINGLETON(Classname, doNotRecreateAfterDeletion) \
185 \
186  static juce::SingletonHolder<Classname, juce::CriticalSection, doNotRecreateAfterDeletion> singletonHolder; \
187  friend juce::SingletonHolder<Classname, juce::CriticalSection, doNotRecreateAfterDeletion>; \
188 \
189  static Classname* JUCE_CALLTYPE getInstance() { return singletonHolder.get(); } \
190  static Classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept { return singletonHolder.instance; } \
191  static void JUCE_CALLTYPE deleteInstance() noexcept { singletonHolder.deleteInstance(); } \
192  void clearSingletonInstance() noexcept { singletonHolder.clear (this); }
193 
194 
195 //==============================================================================
201 #define JUCE_IMPLEMENT_SINGLETON(Classname) \
202 \
203  decltype (Classname::singletonHolder) Classname::singletonHolder;
204 
205 
206 //==============================================================================
226 #define JUCE_DECLARE_SINGLETON_SINGLETHREADED(Classname, doNotRecreateAfterDeletion) \
227 \
228  static juce::SingletonHolder<Classname, juce::DummyCriticalSection, doNotRecreateAfterDeletion> singletonHolder; \
229  friend decltype (singletonHolder); \
230 \
231  static Classname* JUCE_CALLTYPE getInstance() { return singletonHolder.get(); } \
232  static Classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept { return singletonHolder.instance; } \
233  static void JUCE_CALLTYPE deleteInstance() noexcept { singletonHolder.deleteInstance(); } \
234  void clearSingletonInstance() noexcept { singletonHolder.clear (this); }
235 
236 
237 //==============================================================================
252 #define JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL(Classname) \
253 \
254  static juce::SingletonHolder<Classname, juce::DummyCriticalSection, false> singletonHolder; \
255  friend decltype (singletonHolder); \
256 \
257  static Classname* JUCE_CALLTYPE getInstance() { return singletonHolder.getWithoutChecking(); } \
258  static Classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept { return singletonHolder.instance; } \
259  static void JUCE_CALLTYPE deleteInstance() noexcept { singletonHolder.deleteInstance(); } \
260  void clearSingletonInstance() noexcept { singletonHolder.clear (this); }
261 
262 
263 //==============================================================================
264 #ifndef DOXYGEN
265  // These are ancient macros, and have now been updated with new names to match the JUCE style guide,
266  // so please update your code to use the newer versions!
267  #define juce_DeclareSingleton(Classname, doNotRecreate) JUCE_DECLARE_SINGLETON(Classname, doNotRecreate)
268  #define juce_DeclareSingleton_SingleThreaded(Classname, doNotRecreate) JUCE_DECLARE_SINGLETON_SINGLETHREADED(Classname, doNotRecreate)
269  #define juce_DeclareSingleton_SingleThreaded_Minimal(Classname) JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL(Classname)
270  #define juce_ImplementSingleton(Classname) JUCE_IMPLEMENT_SINGLETON(Classname)
271  #define juce_ImplementSingleton_SingleThreaded(Classname) JUCE_IMPLEMENT_SINGLETON(Classname)
272 #endif
273 
274 } // namespace juce
void clear(Type *expectedObject) noexcept