OpenShot Library | OpenShotAudio  0.2.2
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 
27 namespace 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 */
84 template <typename SharedObjectType>
86 {
87 public:
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 
134 private:
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 /** @}*/
Automatically locks and unlocks a mutex object.
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 * operator->() const noexcept
Returns the shared object.
SharedResourcePointer()
Creates an instance of the shared object.
SharedObjectType & getObject() const noexcept
Returns the object that this pointer references.
SharedObjectType & get() const noexcept
Returns the shared object.
A simple spin-lock class that can be used as a simple, low-overhead mutex for uncontended situations.
Definition: juce_SpinLock.h:46
GenericScopedLock< SpinLock > ScopedLockType
Provides the type of scoped lock to use for locking a SpinLock.
Definition: juce_SpinLock.h:77