CmResourceHandle.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #pragma once
  2. #include "CmIReflectable.h"
  3. namespace CamelotFramework
  4. {
  5. template <typename T>
  6. class ResourceHandle;
  7. struct CM_EXPORT ResourceHandleData
  8. {
  9. ResourceHandleData()
  10. :mIsCreated(false)
  11. { }
  12. std::shared_ptr<Resource> mPtr;
  13. String mUUID;
  14. bool mIsCreated;
  15. };
  16. class CM_EXPORT ResourceHandleBase : public IReflectable
  17. {
  18. public:
  19. /**
  20. * @brief Checks if the resource is loaded
  21. */
  22. bool isLoaded() const;
  23. /**
  24. * @brief Blocks the current thread until the resource is fully loaded.
  25. *
  26. * @note Careful not to call this on the thread that does the loading.
  27. */
  28. void synchronize() const;
  29. /**
  30. * @brief Returns the UUID of the resource the handle is referring to.
  31. */
  32. const String& getUUID() const { return mData != nullptr ? mData->mUUID : StringUtil::BLANK; }
  33. /**
  34. * @brief Gets the handle data. For internal use only.
  35. */
  36. const std::shared_ptr<ResourceHandleData>& getHandleData() const { return mData; }
  37. protected:
  38. ResourceHandleBase();
  39. std::shared_ptr<ResourceHandleData> mData;
  40. /**
  41. * @brief Sets the created flag to true and assigns the resource pointer. Called
  42. * by the constructors, or if you constructed just using a UUID, then you need to
  43. * call this manually before you can access the resource from this handle.
  44. *
  45. * @note Two set construction is sometimes required due to multithreaded nature of resource loading.
  46. */
  47. void setResourcePtr(std::shared_ptr<Resource> ptr);
  48. private:
  49. friend class Resources;
  50. CM_STATIC_THREAD_SYNCHRONISER(mResourceCreatedCondition)
  51. CM_STATIC_MUTEX(mResourceCreatedMutex)
  52. protected:
  53. inline void throwIfNotLoaded() const;
  54. /************************************************************************/
  55. /* RTTI */
  56. /************************************************************************/
  57. public:
  58. friend class ResourceHandleRTTI;
  59. static RTTITypeBase* getRTTIStatic();
  60. virtual RTTITypeBase* getRTTI() const;
  61. };
  62. template <typename T>
  63. class ResourceHandle : public ResourceHandleBase
  64. {
  65. public:
  66. ResourceHandle()
  67. :ResourceHandleBase()
  68. { }
  69. // Note: This constructor requires you to call "resolve" with the actual resource pointer,
  70. // before the resource is considered as loaded
  71. ResourceHandle(const String& uuid)
  72. :ResourceHandleBase()
  73. {
  74. mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
  75. mData->mUUID = uuid;
  76. }
  77. template <typename T1>
  78. ResourceHandle(const ResourceHandle<T1>& ptr)
  79. :ResourceHandleBase()
  80. {
  81. mData = ptr.getHandleData();
  82. }
  83. operator ResourceHandle<Resource>()
  84. {
  85. return ResourceHandle<Resource>(*this);
  86. }
  87. T* operator->() const { return get(); }
  88. T& operator*() const { return *get(); }
  89. ResourceHandle<T>& operator=(std::nullptr_t ptr)
  90. {
  91. mData = nullptr;
  92. return *this;
  93. }
  94. template<class _Ty>
  95. struct CM_Bool_struct
  96. {
  97. int _Member;
  98. };
  99. // Conversion to bool
  100. // (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
  101. operator int CM_Bool_struct<T>::*() const
  102. {
  103. return ((mData != nullptr && mData->mPtr != nullptr) ? &CM_Bool_struct<T>::_Member : 0);
  104. }
  105. T* get() const
  106. {
  107. throwIfNotLoaded();
  108. return reinterpret_cast<T*>(mData->mPtr.get());
  109. }
  110. std::shared_ptr<T> getInternalPtr() const
  111. {
  112. throwIfNotLoaded();
  113. return std::static_pointer_cast<T>(mData->mPtr);
  114. }
  115. private:
  116. friend class Resource;
  117. explicit ResourceHandle(T* ptr)
  118. :ResourceHandleBase()
  119. {
  120. mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
  121. setResourcePtr(std::shared_ptr<Resource>(ptr));
  122. }
  123. ResourceHandle(std::shared_ptr<T> ptr)
  124. :ResourceHandleBase()
  125. {
  126. mData = cm_shared_ptr<ResourceHandleData, PoolAlloc>();
  127. setResourcePtr(ptr);
  128. }
  129. };
  130. template<class _Ty1, class _Ty2>
  131. ResourceHandle<_Ty1> static_resource_cast(const ResourceHandle<_Ty2>& other)
  132. {
  133. return ResourceHandle<_Ty1>(other);
  134. }
  135. template<class _Ty1, class _Ty2>
  136. bool operator==(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
  137. {
  138. if(_Left.getHandleData() != nullptr && _Right.getHandleData() != nullptr)
  139. return _Left.getHandleData()->mPtr == _Right.getHandleData()->mPtr;
  140. return _Left.getHandleData() == _Right.getHandleData();
  141. }
  142. template<class _Ty1, class _Ty2>
  143. bool operator!=(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
  144. {
  145. return (!(_Left == _Right));
  146. }
  147. }