Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

smartpointer.h 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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. //-----------------------------------------------------------------------------
  16. #pragma once
  17. #include "pluginterfaces/base/fplatform.h"
  18. #if SMTG_CPP11_STDLIBSUPPORT
  19. #include <utility>
  20. #endif
  21. //------------------------------------------------------------------------
  22. namespace Steinberg {
  23. //------------------------------------------------------------------------
  24. // IPtr
  25. //------------------------------------------------------------------------
  26. /** IPtr - Smart pointer template class.
  27. \ingroup pluginBase
  28. - can be used as an I* pointer
  29. - handles refCount of the interface
  30. - Usage example:
  31. \code
  32. IPtr<IPath> path (sharedPath);
  33. if (path)
  34. path->ascend ();
  35. \endcode
  36. */
  37. template <class I>
  38. class IPtr
  39. {
  40. public:
  41. //------------------------------------------------------------------------
  42. inline IPtr (I* ptr, bool addRef = true);
  43. inline IPtr (const IPtr&);
  44. template <class T>
  45. inline IPtr (const IPtr<T>& other) : ptr (other.get ())
  46. {
  47. if (ptr)
  48. ptr->addRef ();
  49. }
  50. inline IPtr ();
  51. inline ~IPtr ();
  52. inline I* operator= (I* ptr);
  53. inline IPtr& operator= (const IPtr& other);
  54. template <class T>
  55. inline IPtr& operator= (const IPtr<T>& other)
  56. {
  57. operator= (other.get ());
  58. return *this;
  59. }
  60. inline operator I* () const { return ptr; } // act as I*
  61. inline I* operator-> () const { return ptr; } // act as I*
  62. inline I* get () const { return ptr; }
  63. #if SMTG_CPP11_STDLIBSUPPORT
  64. inline IPtr (IPtr<I>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
  65. template <typename T>
  66. inline IPtr (IPtr<T>&& movePtr) SMTG_NOEXCEPT : ptr (movePtr.take ()) { }
  67. inline IPtr& operator= (IPtr<I>&& movePtr) SMTG_NOEXCEPT
  68. {
  69. if (ptr)
  70. ptr->release ();
  71. ptr = movePtr.take ();
  72. return *this;
  73. }
  74. template <typename T>
  75. inline IPtr& operator= (IPtr<T>&& movePtr)
  76. {
  77. if (ptr)
  78. ptr->release ();
  79. ptr = movePtr.take ();
  80. return *this;
  81. }
  82. #endif
  83. inline void reset (I* obj = nullptr)
  84. {
  85. if (ptr)
  86. ptr->release();
  87. ptr = obj;
  88. }
  89. I* take () SMTG_NOEXCEPT
  90. {
  91. I* out = ptr;
  92. ptr = nullptr;
  93. return out;
  94. }
  95. template <typename T>
  96. static IPtr<T> adopt (T* obj) SMTG_NOEXCEPT { return IPtr<T> (obj, false); }
  97. //------------------------------------------------------------------------
  98. protected:
  99. I* ptr;
  100. };
  101. //------------------------------------------------------------------------
  102. template <class I>
  103. inline IPtr<I>::IPtr (I* _ptr, bool addRef) : ptr (_ptr)
  104. {
  105. if (ptr && addRef)
  106. ptr->addRef ();
  107. }
  108. //------------------------------------------------------------------------
  109. template <class I>
  110. inline IPtr<I>::IPtr (const IPtr<I>& other) : ptr (other.ptr)
  111. {
  112. if (ptr)
  113. ptr->addRef ();
  114. }
  115. //------------------------------------------------------------------------
  116. template <class I>
  117. inline IPtr<I>::IPtr () : ptr (0)
  118. {
  119. }
  120. //------------------------------------------------------------------------
  121. template <class I>
  122. inline IPtr<I>::~IPtr ()
  123. {
  124. if (ptr)
  125. {
  126. ptr->release ();
  127. ptr = nullptr; //TODO_CORE: how much does this cost? is this something hiding for us?
  128. }
  129. }
  130. //------------------------------------------------------------------------
  131. template <class I>
  132. inline I* IPtr<I>::operator= (I* _ptr)
  133. {
  134. if (_ptr != ptr)
  135. {
  136. if (ptr)
  137. ptr->release ();
  138. ptr = _ptr;
  139. if (ptr)
  140. ptr->addRef ();
  141. }
  142. return ptr;
  143. }
  144. //------------------------------------------------------------------------
  145. template <class I>
  146. inline IPtr<I>& IPtr<I>::operator= (const IPtr<I>& _ptr)
  147. {
  148. operator= (_ptr.ptr);
  149. return *this;
  150. }
  151. //------------------------------------------------------------------------
  152. /** OPtr - "owning" smart pointer used for newly created FObjects.
  153. \ingroup pluginBase
  154. FUnknown implementations are supposed to have a refCount of 1 right after creation.
  155. So using an IPtr on newly created objects would lead to a leak.
  156. Instead the OPtr can be used in this case. \n
  157. Example:
  158. \code
  159. OPtr<IPath> path = FHostCreate (IPath, hostClasses);
  160. // no release is needed...
  161. \endcode
  162. The assignment operator takes ownership of a new object and releases the old.
  163. So its safe to write:
  164. \code
  165. OPtr<IPath> path = FHostCreate (IPath, hostClasses);
  166. path = FHostCreate (IPath, hostClasses);
  167. path = 0;
  168. \endcode
  169. This is the difference to using an IPtr with addRef=false.
  170. \code
  171. // DONT DO THIS:
  172. IPtr<IPath> path (FHostCreate (IPath, hostClasses), false);
  173. path = FHostCreate (IPath, hostClasses);
  174. path = 0;
  175. \endcode
  176. This will lead to a leak!
  177. */
  178. template <class I>
  179. class OPtr : public IPtr<I>
  180. {
  181. public:
  182. //------------------------------------------------------------------------
  183. inline OPtr (I* p) : IPtr<I> (p, false) {}
  184. inline OPtr (const IPtr<I>& p) : IPtr<I> (p) {}
  185. inline OPtr (const OPtr<I>& p) : IPtr<I> (p) {}
  186. inline OPtr () {}
  187. inline I* operator= (I* _ptr)
  188. {
  189. if (_ptr != this->ptr)
  190. {
  191. if (this->ptr)
  192. this->ptr->release ();
  193. this->ptr = _ptr;
  194. }
  195. return this->ptr;
  196. }
  197. };
  198. //------------------------------------------------------------------------
  199. /** Assigning newly created object to an IPtr.
  200. Example:
  201. \code
  202. IPtr<IPath> path = owned (FHostCreate (IPath, hostClasses));
  203. \endcode
  204. which is a slightly shorter form of writing:
  205. \code
  206. IPtr<IPath> path = OPtr<IPath> (FHostCreate (IPath, hostClasses));
  207. \endcode
  208. */
  209. template <class I>
  210. IPtr<I> owned (I* p)
  211. {
  212. return IPtr<I> (p, false);
  213. }
  214. /** Assigning shared object to an IPtr.
  215. Example:
  216. \code
  217. IPtr<IPath> path = shared (iface.getXY ());
  218. \endcode
  219. */
  220. template <class I>
  221. IPtr<I> shared (I* p)
  222. {
  223. return IPtr<I> (p, true);
  224. }
  225. #if SMTG_CPP11_STDLIBSUPPORT
  226. //------------------------------------------------------------------------
  227. // Ownership functionality
  228. //------------------------------------------------------------------------
  229. namespace SKI {
  230. namespace Detail {
  231. struct Adopt;
  232. } // Detail
  233. /** Strong typedef for shared reference counted objects.
  234. * Use SKI::adopt to unwrap the provided object.
  235. * @tparam T Referenced counted type.
  236. */
  237. template <typename T>
  238. class Shared
  239. {
  240. friend struct Detail::Adopt;
  241. T* obj = nullptr;
  242. };
  243. /** Strong typedef for transferring the ownership of reference counted objects.
  244. * Use SKI::adopt to unwrap the provided object.
  245. * After calling adopt the reference in this object is null.
  246. * @tparam T Referenced counted type.
  247. */
  248. template <typename T>
  249. class Owned
  250. {
  251. friend struct Detail::Adopt;
  252. T* obj = nullptr;
  253. };
  254. /** Strong typedef for using reference counted objects.
  255. * Use SKI::adopt to unwrap the provided object.
  256. * After calling adopt the reference in this object is null.
  257. * @tparam T Referenced counted type.
  258. */
  259. template <typename T>
  260. class Used
  261. {
  262. friend struct Detail::Adopt;
  263. T* obj = nullptr;
  264. };
  265. namespace Detail {
  266. struct Adopt
  267. {
  268. template <typename T>
  269. static IPtr<T> adopt (Shared<T>& ref)
  270. {
  271. using Steinberg::shared;
  272. return shared (ref.obj);
  273. }
  274. template <typename T>
  275. static IPtr<T> adopt (Owned<T>& ref)
  276. {
  277. using Steinberg::owned;
  278. IPtr<T> out = owned (ref.obj);
  279. ref.obj = nullptr;
  280. return out;
  281. }
  282. template <typename T>
  283. static T* adopt (Used<T>& ref)
  284. {
  285. return ref.obj;
  286. }
  287. template <template <typename> class OwnerType, typename T>
  288. static OwnerType<T> toOwnerType (T* obj)
  289. {
  290. OwnerType<T> out;
  291. out.obj = obj;
  292. return out;
  293. }
  294. };
  295. } // Detail
  296. /** Common function to adopt referenced counted object.
  297. * @tparam T Referenced counted type.
  298. * @param ref The reference to be adopted in a smart pointer.
  299. */
  300. template <typename T>
  301. IPtr<T> adopt (Shared<T>& ref) { return Detail::Adopt::adopt (ref); }
  302. template <typename T>
  303. IPtr<T> adopt (Shared<T>&& ref) { return Detail::Adopt::adopt (ref); }
  304. /** Common function to adopt referenced counted object.
  305. * @tparam T Referenced counted type.
  306. * @param ref The reference to be adopted in a smart pointer.
  307. */
  308. template <typename T>
  309. IPtr<T> adopt (Owned<T>& ref) { return Detail::Adopt::adopt (ref); }
  310. template <typename T>
  311. IPtr<T> adopt (Owned<T>&& ref) { return Detail::Adopt::adopt (ref); }
  312. /** Common function to adopt referenced counted object.
  313. * @tparam T Referenced counted type.
  314. * @param ref The reference to be adopted in a smart pointer.
  315. */
  316. template <typename T>
  317. T* adopt (Used<T>& ref) { return Detail::Adopt::adopt (ref); }
  318. template <typename T>
  319. T* adopt (Used<T>&& ref) { return Detail::Adopt::adopt (ref); }
  320. /** Common function to wrap owned instances. */
  321. template <typename T>
  322. Owned<T> toOwned (T* obj) { return Detail::Adopt::toOwnerType<Owned> (obj); }
  323. /** Common function to wrap shared instances. */
  324. template <typename T>
  325. Shared<T> toShared (T* obj) { return Detail::Adopt::toOwnerType<Shared> (obj); }
  326. /** Common function to wrap used instances. */
  327. template <typename T>
  328. Used<T> toUsed (T* obj) { return Detail::Adopt::toOwnerType<Used> (obj); }
  329. //------------------------------------------------------------------------
  330. } // SKI
  331. #endif
  332. } // Steinberg