Fix last commit
[carla.git] / source / includes / vst3sdk / pluginterfaces / base / smartpointer.h
blob99dd037303d5759e2918c55a0144822edf25f4d4
1 //-----------------------------------------------------------------------------
2 // Project : SDK Core
3 //
4 // Category : SDK Core Interfaces
5 // Filename : pluginterfaces/base/smartpointer.h
6 // Created by : Steinberg, 01/2004
7 // Description : Basic Interface
8 //
9 //-----------------------------------------------------------------------------
10 // This file is part of a Steinberg SDK. It is subject to the license terms
11 // in the LICENSE file found in the top-level directory of this distribution
12 // and at www.steinberg.net/sdklicenses.
13 // No part of the SDK, including this file, may be copied, modified, propagated,
14 // or distributed except according to the terms contained in the LICENSE file.
15 //-----------------------------------------------------------------------------
17 #pragma once
19 #include "pluginterfaces/base/fplatform.h"
20 #if SMTG_CPP11_STDLIBSUPPORT
21 #include <utility>
22 #endif
24 //------------------------------------------------------------------------
25 namespace Steinberg {
27 //------------------------------------------------------------------------
28 // IPtr
29 //------------------------------------------------------------------------
30 /** IPtr - Smart pointer template class.
31 \ingroup pluginBase
33 - can be used as an I* pointer
34 - handles refCount of the interface
35 - Usage example:
36 \code
37 IPtr<IPath> path (sharedPath);
38 if (path)
39 path->ascend ();
40 \endcode
42 template <class I>
43 class IPtr
45 public:
46 //------------------------------------------------------------------------
47 inline IPtr (I* ptr, bool addRef = true);
48 inline IPtr (const IPtr&);
50 template <class T>
51 inline IPtr (const IPtr<T>& other) : ptr (other.get ())
53 if (ptr)
54 ptr->addRef ();
57 inline IPtr ();
58 inline ~IPtr ();
60 inline I* operator= (I* ptr);
62 inline IPtr& operator= (const IPtr& other);
64 template <class T>
65 inline IPtr& operator= (const IPtr<T>& other)
67 operator= (other.get ());
68 return *this;
71 inline operator I* () const { return ptr; } // act as I*
72 inline I* operator-> () const { return ptr; } // act as I*
74 inline I* get () const { return ptr; }
76 #if SMTG_CPP11_STDLIBSUPPORT
77 inline IPtr (IPtr<I>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
79 template <typename T>
80 inline IPtr (IPtr<T>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
82 inline IPtr& operator= (IPtr<I>&& movePtr) SMTG_NOEXCEPT
84 if (ptr)
85 ptr->release ();
87 ptr = movePtr.take ();
88 return *this;
91 template <typename T>
92 inline IPtr& operator= (IPtr<T>&& movePtr)
94 if (ptr)
95 ptr->release ();
97 ptr = movePtr.take ();
98 return *this;
100 #endif
102 inline void reset (I* obj = nullptr)
104 if (ptr)
105 ptr->release();
106 ptr = obj;
109 I* take () SMTG_NOEXCEPT
111 I* out = ptr;
112 ptr = nullptr;
113 return out;
116 template <typename T>
117 static IPtr<T> adopt (T* obj) SMTG_NOEXCEPT { return IPtr<T> (obj, false); }
119 //------------------------------------------------------------------------
120 protected:
121 I* ptr;
124 //------------------------------------------------------------------------
125 template <class I>
126 inline IPtr<I>::IPtr (I* _ptr, bool addRef) : ptr (_ptr)
128 if (ptr && addRef)
129 ptr->addRef ();
132 //------------------------------------------------------------------------
133 template <class I>
134 inline IPtr<I>::IPtr (const IPtr<I>& other) : ptr (other.ptr)
136 if (ptr)
137 ptr->addRef ();
140 //------------------------------------------------------------------------
141 template <class I>
142 inline IPtr<I>::IPtr () : ptr (0)
146 //------------------------------------------------------------------------
147 template <class I>
148 inline IPtr<I>::~IPtr ()
150 if (ptr)
152 ptr->release ();
153 ptr = nullptr; //TODO_CORE: how much does this cost? is this something hiding for us?
157 //------------------------------------------------------------------------
158 template <class I>
159 inline I* IPtr<I>::operator= (I* _ptr)
161 if (_ptr != ptr)
163 if (ptr)
164 ptr->release ();
165 ptr = _ptr;
166 if (ptr)
167 ptr->addRef ();
169 return ptr;
172 //------------------------------------------------------------------------
173 template <class I>
174 inline IPtr<I>& IPtr<I>::operator= (const IPtr<I>& _ptr)
176 operator= (_ptr.ptr);
177 return *this;
180 //------------------------------------------------------------------------
181 /** OPtr - "owning" smart pointer used for newly created FObjects.
182 \ingroup pluginBase
184 FUnknown implementations are supposed to have a refCount of 1 right after creation.
185 So using an IPtr on newly created objects would lead to a leak.
186 Instead the OPtr can be used in this case. \n
187 Example:
188 \code
189 OPtr<IPath> path = FHostCreate (IPath, hostClasses);
190 // no release is needed...
191 \endcode
192 The assignment operator takes ownership of a new object and releases the old.
193 So its safe to write:
194 \code
195 OPtr<IPath> path = FHostCreate (IPath, hostClasses);
196 path = FHostCreate (IPath, hostClasses);
197 path = 0;
198 \endcode
199 This is the difference to using an IPtr with addRef=false.
200 \code
201 // DONT DO THIS:
202 IPtr<IPath> path (FHostCreate (IPath, hostClasses), false);
203 path = FHostCreate (IPath, hostClasses);
204 path = 0;
205 \endcode
206 This will lead to a leak!
208 template <class I>
209 class OPtr : public IPtr<I>
211 public:
212 //------------------------------------------------------------------------
213 inline OPtr (I* p) : IPtr<I> (p, false) {}
214 inline OPtr (const IPtr<I>& p) : IPtr<I> (p) {}
215 inline OPtr (const OPtr<I>& p) : IPtr<I> (p) {}
216 inline OPtr () {}
217 inline I* operator= (I* _ptr)
219 if (_ptr != this->ptr)
221 if (this->ptr)
222 this->ptr->release ();
223 this->ptr = _ptr;
225 return this->ptr;
229 //------------------------------------------------------------------------
230 /** Assigning newly created object to an IPtr.
231 Example:
232 \code
233 IPtr<IPath> path = owned (FHostCreate (IPath, hostClasses));
234 \endcode
235 which is a slightly shorter form of writing:
236 \code
237 IPtr<IPath> path = OPtr<IPath> (FHostCreate (IPath, hostClasses));
238 \endcode
240 template <class I>
241 IPtr<I> owned (I* p)
243 return IPtr<I> (p, false);
246 /** Assigning shared object to an IPtr.
247 Example:
248 \code
249 IPtr<IPath> path = shared (iface.getXY ());
250 \endcode
252 template <class I>
253 IPtr<I> shared (I* p)
255 return IPtr<I> (p, true);
258 #if SMTG_CPP11_STDLIBSUPPORT
259 //------------------------------------------------------------------------
260 // Ownership functionality
261 //------------------------------------------------------------------------
262 namespace SKI {
263 namespace Detail {
264 struct Adopt;
265 } // Detail
267 /** Strong typedef for shared reference counted objects.
268 * Use SKI::adopt to unwrap the provided object.
269 * @tparam T Referenced counted type.
271 template <typename T>
272 class Shared
274 friend struct Detail::Adopt;
275 T* obj = nullptr;
278 /** Strong typedef for transferring the ownership of reference counted objects.
279 * Use SKI::adopt to unwrap the provided object.
280 * After calling adopt the reference in this object is null.
281 * @tparam T Referenced counted type.
283 template <typename T>
284 class Owned
286 friend struct Detail::Adopt;
287 T* obj = nullptr;
290 /** Strong typedef for using reference counted objects.
291 * Use SKI::adopt to unwrap the provided object.
292 * After calling adopt the reference in this object is null.
293 * @tparam T Referenced counted type.
295 template <typename T>
296 class Used
298 friend struct Detail::Adopt;
299 T* obj = nullptr;
302 namespace Detail {
304 struct Adopt
306 template <typename T>
307 static IPtr<T> adopt (Shared<T>& ref)
309 using Steinberg::shared;
310 return shared (ref.obj);
313 template <typename T>
314 static IPtr<T> adopt (Owned<T>& ref)
316 using Steinberg::owned;
317 IPtr<T> out = owned (ref.obj);
318 ref.obj = nullptr;
319 return out;
322 template <typename T>
323 static T* adopt (Used<T>& ref)
325 return ref.obj;
328 template <template <typename> class OwnerType, typename T>
329 static OwnerType<T> toOwnerType (T* obj)
331 OwnerType<T> out;
332 out.obj = obj;
333 return out;
337 } // Detail
339 /** Common function to adopt referenced counted object.
340 * @tparam T Referenced counted type.
341 * @param ref The reference to be adopted in a smart pointer.
343 template <typename T>
344 IPtr<T> adopt (Shared<T>& ref) { return Detail::Adopt::adopt (ref); }
346 template <typename T>
347 IPtr<T> adopt (Shared<T>&& ref) { return Detail::Adopt::adopt (ref); }
349 /** Common function to adopt referenced counted object.
350 * @tparam T Referenced counted type.
351 * @param ref The reference to be adopted in a smart pointer.
353 template <typename T>
354 IPtr<T> adopt (Owned<T>& ref) { return Detail::Adopt::adopt (ref); }
356 template <typename T>
357 IPtr<T> adopt (Owned<T>&& ref) { return Detail::Adopt::adopt (ref); }
359 /** Common function to adopt referenced counted object.
360 * @tparam T Referenced counted type.
361 * @param ref The reference to be adopted in a smart pointer.
363 template <typename T>
364 T* adopt (Used<T>& ref) { return Detail::Adopt::adopt (ref); }
366 template <typename T>
367 T* adopt (Used<T>&& ref) { return Detail::Adopt::adopt (ref); }
369 /** Common function to wrap owned instances. */
370 template <typename T>
371 Owned<T> toOwned (T* obj) { return Detail::Adopt::toOwnerType<Owned> (obj); }
373 /** Common function to wrap shared instances. */
374 template <typename T>
375 Shared<T> toShared (T* obj) { return Detail::Adopt::toOwnerType<Shared> (obj); }
377 /** Common function to wrap used instances. */
378 template <typename T>
379 Used<T> toUsed (T* obj) { return Detail::Adopt::toOwnerType<Used> (obj); }
381 //------------------------------------------------------------------------
382 } // SKI
383 #endif
384 } // Steinberg