| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- #pragma once
- #include "CmIReflectable.h"
- namespace CamelotFramework
- {
- template <typename T>
- class ResourceHandle;
- struct CM_EXPORT ResourceHandleData
- {
- ResourceHandleData()
- :mIsCreated(false)
- { }
- std::shared_ptr<Resource> mPtr;
- String mUUID;
- bool mIsCreated;
- };
- class CM_EXPORT ResourceHandleBase : public IReflectable
- {
- public:
- /**
- * @brief Checks if the resource is loaded
- */
- bool isLoaded() const;
- /**
- * @brief Blocks the current thread until the resource is fully loaded.
- *
- * @note Careful not to call this on the thread that does the loading.
- */
- void synchronize() const;
- /**
- * @brief Returns the UUID of the resource the handle is referring to.
- */
- const String& getUUID() const { return mData->mUUID; }
- /**
- * @brief Gets the handle data. For internal use only.
- */
- std::shared_ptr<ResourceHandleData> getHandleData() const { return mData; }
- protected:
- ResourceHandleBase();
- std::shared_ptr<ResourceHandleData> mData;
- void init(Resource* ptr);
- void init(std::shared_ptr<Resource> ptr);
- template <typename T1>
- void init(const ResourceHandle<T1>& ptr)
- {
- mData = ptr.mData;
- }
- private:
- friend class Resources;
- CM_STATIC_THREAD_SYNCHRONISER(mResourceCreatedCondition)
- CM_STATIC_MUTEX(mResourceCreatedMutex)
- /**
- * @brief Sets the created flag to true. Should only be called
- * by Resources class after loading of the resource is fully done.
- */
- void resolve(std::shared_ptr<Resource> ptr);
- /**
- * @brief Sets an uuid of the ResourceHandle. Should only be called by
- * Resources class.
- */
- void ResourceHandleBase::setUUID(const String& uuid);
- protected:
- inline void throwIfNotLoaded() const;
- /************************************************************************/
- /* RTTI */
- /************************************************************************/
- public:
- friend class ResourceHandleRTTI;
- static RTTITypeBase* getRTTIStatic();
- virtual RTTITypeBase* getRTTI() const;
- };
- template <typename T>
- class ResourceHandle : public ResourceHandleBase
- {
- public:
- ResourceHandle()
- :ResourceHandleBase()
- { }
- template <typename T1>
- ResourceHandle(const ResourceHandle<T1>& ptr)
- :ResourceHandleBase()
- {
- mData = ptr.getHandleData();
- }
- operator ResourceHandle<Resource>()
- {
- return ResourceHandle<Resource>(*this);
- }
- // TODO Low priority - User can currently try to access these even if resource ptr is not resolved
- T* get() const
- {
- throwIfNotLoaded();
- return reinterpret_cast<T*>(mData->mPtr.get());
- }
- T* operator->() const { return get(); }
- T& operator*() const { return *get(); }
- std::shared_ptr<T> getInternalPtr() const
- {
- throwIfNotLoaded();
- return std::static_pointer_cast<T>(mData->mPtr);
- }
- /**
- * @brief Releases the reference held by this handle.
- */
- void reset()
- {
- mData = cm_shared_ptr<ResourceHandleData, ScratchAlloc>();
- }
- template<class _Ty>
- struct CM_Bool_struct
- {
- int _Member;
- };
- // Conversion to bool
- // (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
- operator int CM_Bool_struct<T>::*() const
- {
- return (((mData->mPtr != nullptr)) ? &CM_Bool_struct<T>::_Member : 0);
- }
- private:
- friend class Resource;
- explicit ResourceHandle(T* ptr)
- :ResourceHandleBase()
- {
- init(ptr);
- }
- ResourceHandle(std::shared_ptr<T> ptr)
- :ResourceHandleBase()
- {
- init(ptr);
- }
- };
- template<class _Ty1, class _Ty2>
- ResourceHandle<_Ty1> static_resource_cast(const ResourceHandle<_Ty2>& other)
- {
- return ResourceHandle<_Ty1>(other);
- }
- template<class _Ty1, class _Ty2>
- bool operator==(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
- {
- return (_Left.get() == _Right.get());
- }
- template<class _Ty1, class _Ty2>
- bool operator!=(const ResourceHandle<_Ty1>& _Left, const ResourceHandle<_Ty2>& _Right)
- {
- return (!(_Left == _Right));
- }
- }
|