BsResourceHandle.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #pragma once
  2. #include "BsIReflectable.h"
  3. namespace BansheeEngine
  4. {
  5. /**
  6. * @brief Data that is shared between all resource handles.
  7. */
  8. struct BS_CORE_EXPORT ResourceHandleData
  9. {
  10. ResourceHandleData()
  11. :mIsCreated(false), mRefCount(0)
  12. { }
  13. SPtr<Resource> mPtr;
  14. String mUUID;
  15. bool mIsCreated;
  16. UINT32 mRefCount;
  17. };
  18. /**
  19. * @brief Base class containing common functionality for resource handles.
  20. */
  21. class BS_CORE_EXPORT ResourceHandleBase : public IReflectable
  22. {
  23. public:
  24. virtual ~ResourceHandleBase();
  25. /**
  26. * @brief Checks if the resource is loaded. Until resource is loaded this handle
  27. * is invalid and you may not get the internal resource from it.
  28. *
  29. * @param checkDependencies If true, and if resource has any dependencies, this method will
  30. * also check if they are loaded.
  31. */
  32. bool isLoaded(bool checkDependencies = true) const;
  33. /**
  34. * @brief Blocks the current thread until the resource is fully loaded.
  35. *
  36. * @note Careful not to call this on the thread that does the loading.
  37. */
  38. void blockUntilLoaded(bool waitForDependencies = true) const;
  39. /**
  40. * @brief Returns the UUID of the resource the handle is referring to.
  41. */
  42. const String& getUUID() const { return mData != nullptr ? mData->mUUID : StringUtil::BLANK; }
  43. /**
  44. * @brief Gets the handle data. For internal use only.
  45. */
  46. const SPtr<ResourceHandleData>& getHandleData() const { return mData; }
  47. protected:
  48. ResourceHandleBase();
  49. /**
  50. * @brief Sets the created flag to true and assigns the resource pointer. Called
  51. * by the constructors, or if you constructed just using a UUID, then you need to
  52. * call this manually before you can access the resource from this handle.
  53. *
  54. * @note This is needed because two part construction is required due to
  55. * multithreaded nature of resource loading.
  56. * Internal method.
  57. */
  58. void setHandleData(const SPtr<Resource>& ptr, const String& uuid);
  59. /** @note All handles to the same source must share this same handle data. Otherwise things
  60. * like counting number of references or replacing pointed to resource become impossible
  61. * without additional logic. */
  62. SPtr<ResourceHandleData> mData;
  63. private:
  64. friend class Resources;
  65. BS_STATIC_THREAD_SYNCHRONISER(mResourceCreatedCondition)
  66. BS_STATIC_MUTEX(mResourceCreatedMutex)
  67. protected:
  68. inline void throwIfNotLoaded() const;
  69. };
  70. /**
  71. * @copydoc ResourceHandleBase
  72. *
  73. * Handles differences in reference counting depending if the handle is normal or weak.
  74. */
  75. template <bool WeakHandle>
  76. class BS_CORE_EXPORT TResourceHandleBase : public ResourceHandleBase { };
  77. /**
  78. * @brief Specialization of TResourceHandleBase for weak handles. Weak handles do no reference counting.
  79. */
  80. template<>
  81. class BS_CORE_EXPORT TResourceHandleBase<true> : public ResourceHandleBase
  82. {
  83. public:
  84. virtual ~TResourceHandleBase() { }
  85. protected:
  86. void addRef() { };
  87. void releaseRef() { };
  88. /************************************************************************/
  89. /* RTTI */
  90. /************************************************************************/
  91. public:
  92. friend class WeakResourceHandleRTTI;
  93. static RTTITypeBase* getRTTIStatic();
  94. virtual RTTITypeBase* getRTTI() const override;
  95. };
  96. /**
  97. * @brief Specialization of TResourceHandleBase for normal (non-weak) handles.
  98. */
  99. template<>
  100. class BS_CORE_EXPORT TResourceHandleBase<false> : public ResourceHandleBase
  101. {
  102. public:
  103. virtual ~TResourceHandleBase() { }
  104. protected:
  105. void addRef() { if (mData) mData->mRefCount++; };
  106. void releaseRef() { if (mData) mData->mRefCount--; };
  107. /************************************************************************/
  108. /* RTTI */
  109. /************************************************************************/
  110. public:
  111. friend class WeakResourceHandleRTTI;
  112. friend class ResourceHandleRTTI;
  113. static RTTITypeBase* getRTTIStatic();
  114. virtual RTTITypeBase* getRTTI() const override;
  115. };
  116. /**
  117. * @brief Represents a handle to a resource. Handles are similar to a smart pointers, but they have two advantages:
  118. * - When loading a resource asynchronously you can be immediately returned the handle
  119. * that you may use throughout the engine. The handle will be made valid as soon as
  120. * the resource is loaded.
  121. * - Handles can be serialized and deserialized, therefore saving/restoring references
  122. * to their original resource.
  123. */
  124. template <typename T, bool WeakHandle>
  125. class TResourceHandle : public TResourceHandleBase<WeakHandle>
  126. {
  127. public:
  128. TResourceHandle()
  129. :TResourceHandleBase()
  130. { }
  131. /**
  132. * @brief Copy constructor.
  133. */
  134. TResourceHandle(const TResourceHandle<T, WeakHandle>& ptr)
  135. :TResourceHandleBase()
  136. {
  137. mData = ptr.getHandleData();
  138. addRef();
  139. }
  140. virtual ~TResourceHandle()
  141. {
  142. releaseRef();
  143. }
  144. /**
  145. * @brief Converts a specific handle to generic Resource handle.
  146. */
  147. operator TResourceHandle<Resource, WeakHandle>() const
  148. {
  149. TResourceHandle<Resource, WeakHandle> handle;
  150. handle.setHandleData(getHandleData());
  151. return handle;
  152. }
  153. /**
  154. * @brief Returns internal resource pointer.
  155. *
  156. * @note Throws exception if handle is invalid.
  157. */
  158. T* operator->() const { return get(); }
  159. /**
  160. * @brief Returns internal resource pointer and dereferences it.
  161. *
  162. * @note Throws exception if handle is invalid.
  163. */
  164. T& operator*() const { return *get(); }
  165. /**
  166. * @brief Clears the handle making it invalid and releases any references
  167. * held to the resource.
  168. */
  169. TResourceHandle<T, WeakHandle>& operator=(std::nullptr_t ptr)
  170. {
  171. releaseRef();
  172. mData = nullptr;
  173. return *this;
  174. }
  175. /**
  176. * @brief Normal assignment operator.
  177. */
  178. TResourceHandle<T, WeakHandle>& operator=(const TResourceHandle<T, WeakHandle>& rhs)
  179. {
  180. setHandleData(rhs.getHandleData());
  181. return *this;
  182. }
  183. template<class _Ty>
  184. struct Bool_struct
  185. {
  186. int _Member;
  187. };
  188. /**
  189. * @brief Allows direct conversion of handle to bool.
  190. *
  191. * @note This is needed because we can't directly convert to bool
  192. * since then we can assign pointer to bool and that's weird.
  193. */
  194. operator int Bool_struct<T>::*() const
  195. {
  196. return ((mData != nullptr && mData->mPtr != nullptr) ? &Bool_struct<T>::_Member : 0);
  197. }
  198. /**
  199. * @brief Returns internal resource pointer and dereferences it.
  200. *
  201. * @note Throws exception if handle is invalid.
  202. */
  203. T* get() const
  204. {
  205. throwIfNotLoaded();
  206. return reinterpret_cast<T*>(mData->mPtr.get());
  207. }
  208. /**
  209. * @brief Returns the internal shared pointer to the resource.
  210. *
  211. * @note Throws exception if handle is invalid.
  212. */
  213. SPtr<T> getInternalPtr() const
  214. {
  215. throwIfNotLoaded();
  216. return std::static_pointer_cast<T>(mData->mPtr);
  217. }
  218. /**
  219. * @brief Converts a handle into a weak handle.
  220. */
  221. TResourceHandle<T, true> getWeak() const
  222. {
  223. TResourceHandle<T, true> handle;
  224. handle.setHandleData(getHandleData());
  225. return handle;
  226. }
  227. protected:
  228. friend Resources;
  229. template<class _T, bool _Weak>
  230. friend class TResourceHandle;
  231. template<class _Ty1, class _Ty2, bool Weak>
  232. friend TResourceHandle<_Ty1, Weak> static_resource_cast(const TResourceHandle<_Ty2, Weak>& other);
  233. /**
  234. * @brief Constructs a new valid handle for the provided resource with the provided UUID.
  235. *
  236. * @note Handle will take ownership of the provided resource pointer, so make sure you don't
  237. * delete it elsewhere.
  238. */
  239. explicit TResourceHandle(T* ptr, const String& uuid)
  240. :TResourceHandleBase()
  241. {
  242. mData = bs_shared_ptr_new<ResourceHandleData>();
  243. addRef();
  244. setHandleData(std::shared_ptr<Resource>(ptr, uuid));
  245. }
  246. /**
  247. * @brief Constructs an invalid handle with the specified UUID. You must call setHandleData
  248. * with the actual resource pointer to make the handle valid.
  249. */
  250. TResourceHandle(const String& uuid)
  251. :TResourceHandleBase()
  252. {
  253. mData = bs_shared_ptr_new<ResourceHandleData>();
  254. mData->mUUID = uuid;
  255. addRef();
  256. }
  257. /**
  258. * @brief Constructs a new valid handle for the provided resource with the provided UUID.
  259. */
  260. TResourceHandle(const SPtr<T> ptr, const String& uuid)
  261. :TResourceHandleBase()
  262. {
  263. mData = bs_shared_ptr_new<ResourceHandleData>();
  264. addRef();
  265. setHandleData(ptr, uuid);
  266. }
  267. /**
  268. * @brief Replaces the internal handle data pointer, effectively transforming the handle into a different handle.
  269. */
  270. void setHandleData(const SPtr<ResourceHandleData>& data)
  271. {
  272. releaseRef();
  273. mData = data;
  274. addRef();
  275. }
  276. /**
  277. * @brief Converts a weak handle into a normal handle.
  278. */
  279. TResourceHandle<T, false> lock() const
  280. {
  281. TResourceHandle<Resource, false> handle;
  282. handle.setHandleData(getHandleData());
  283. return handle;
  284. }
  285. using TResourceHandleBase::setHandleData;
  286. };
  287. template <typename T>
  288. using ResourceHandle = TResourceHandle<T, false>;
  289. template <typename T>
  290. using WeakResourceHandle = TResourceHandle<T, true>;
  291. /**
  292. * @brief Casts one resource handle to another.
  293. */
  294. template<class _Ty1, class _Ty2, bool Weak>
  295. TResourceHandle<_Ty1, Weak> static_resource_cast(const TResourceHandle<_Ty2, Weak>& other)
  296. {
  297. TResourceHandle<_Ty1, Weak> handle;
  298. handle.setHandleData(other.getHandleData());
  299. return handle;
  300. }
  301. /**
  302. * @brief Checks if two handles point to the same resource.
  303. */
  304. template<class _Ty1, bool _Weak1, class _Ty2, bool _Weak2>
  305. bool operator==(const TResourceHandle<_Ty1, _Weak1>& _Left, const TResourceHandle<_Ty2, _Weak2>& _Right)
  306. {
  307. if(_Left.getHandleData() != nullptr && _Right.getHandleData() != nullptr)
  308. return _Left.getHandleData()->mPtr == _Right.getHandleData()->mPtr;
  309. return _Left.getHandleData() == _Right.getHandleData();
  310. }
  311. template<class _Ty1, bool _Weak1, class _Ty2, bool _Weak2>
  312. bool operator!=(const TResourceHandle<_Ty1, _Weak1>& _Left, const TResourceHandle<_Ty2, _Weak2>& _Right)
  313. {
  314. return (!(_Left == _Right));
  315. }
  316. }