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 8.8KB

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