VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_core / memory / juce_SharedResourcePointer.h
blob2f9a526bf763ce7cb7014564c1df91a3f379eabe
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
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.
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.
20 ==============================================================================
23 namespace juce
26 //==============================================================================
27 /**
28 A smart-pointer that automatically creates and manages the lifetime of a
29 shared static instance of a class.
31 The SharedObjectType template type indicates the class to use for the shared
32 object - the only requirements on this class are that it must have a public
33 default constructor and destructor.
35 The SharedResourcePointer offers a pattern that differs from using a singleton or
36 static instance of an object, because it uses reference-counting to make sure that
37 the underlying shared object is automatically created/destroyed according to the
38 number of SharedResourcePointer objects that exist. When the last one is deleted,
39 the underlying object is also immediately destroyed. This allows you to use scoping
40 to manage the lifetime of a shared resource.
42 Note: The construction/deletion of the shared object must not involve any
43 code that makes recursive calls to a SharedResourcePointer, or you'll cause
44 a deadlock.
46 Example:
47 @code
48 // An example of a class that contains the shared data you want to use.
49 struct MySharedData
51 // There's no need to ever create an instance of this class directly yourself,
52 // but it does need a public constructor that does the initialisation.
53 MySharedData()
55 sharedStuff = generateHeavyweightStuff();
58 Array<SomeKindOfData> sharedStuff;
61 struct DataUserClass
63 DataUserClass()
65 // Multiple instances of the DataUserClass will all have the same
66 // shared common instance of MySharedData referenced by their sharedData
67 // member variables.
68 useSharedStuff (sharedData->sharedStuff);
71 // By keeping this pointer as a member variable, the shared resource
72 // is guaranteed to be available for as long as the DataUserClass object.
73 SharedResourcePointer<MySharedData> sharedData;
76 @endcode
78 @tags{Core}
80 template <typename SharedObjectType>
81 class SharedResourcePointer
83 public:
84 /** Creates an instance of the shared object.
85 If other SharedResourcePointer objects for this type already exist, then
86 this one will simply point to the same shared object that they are already
87 using. Otherwise, if this is the first SharedResourcePointer to be created,
88 then a shared object will be created automatically.
90 SharedResourcePointer()
92 initialise();
95 SharedResourcePointer (const SharedResourcePointer&)
97 initialise();
100 /** Destructor.
101 If no other SharedResourcePointer objects exist, this will also delete
102 the shared object to which it refers.
104 ~SharedResourcePointer()
106 auto& holder = getSharedObjectHolder();
107 const SpinLock::ScopedLockType sl (holder.lock);
109 if (--(holder.refCount) == 0)
110 holder.sharedInstance = nullptr;
113 /** Returns the shared object. */
114 operator SharedObjectType*() const noexcept { return sharedObject; }
116 /** Returns the shared object. */
117 SharedObjectType& get() const noexcept { return *sharedObject; }
119 /** Returns the object that this pointer references. */
120 SharedObjectType& getObject() const noexcept { return *sharedObject; }
122 /** Returns the shared object pointer. */
123 SharedObjectType* operator->() const noexcept { return sharedObject; }
125 /** Returns the number of SharedResourcePointers that are currently holding the shared object. */
126 int getReferenceCount() const noexcept { return getSharedObjectHolder().refCount; }
128 private:
129 struct SharedObjectHolder
131 SpinLock lock;
132 std::unique_ptr<SharedObjectType> sharedInstance;
133 int refCount;
136 static SharedObjectHolder& getSharedObjectHolder() noexcept
138 static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { nullptr };
139 return *reinterpret_cast<SharedObjectHolder*> (holder);
142 SharedObjectType* sharedObject;
144 void initialise()
146 auto& holder = getSharedObjectHolder();
147 const SpinLock::ScopedLockType sl (holder.lock);
149 if (++(holder.refCount) == 1)
150 holder.sharedInstance.reset (new SharedObjectType());
152 sharedObject = holder.sharedInstance.get();
155 // There's no need to assign to a SharedResourcePointer because every
156 // instance of the class is exactly the same!
157 SharedResourcePointer& operator= (const SharedResourcePointer&) = delete;
159 JUCE_LEAK_DETECTOR (SharedResourcePointer)
162 } // namespace juce