1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsCorePrerequisites.h"
4#include "Resources/BsResourceHandle.h"
5#include "Resources/BsResource.h"
6#include "Private/RTTI/BsResourceHandleRTTI.h"
7#include "Resources/BsResources.h"
8#include "Managers/BsResourceListenerManager.h"
9#include "BsCoreApplication.h"
10
11namespace bs
12{
13 Signal ResourceHandleBase::mResourceCreatedCondition;
14 Mutex ResourceHandleBase::mResourceCreatedMutex;
15
16 bool ResourceHandleBase::isLoaded(bool checkDependencies) const
17 {
18 bool isLoaded = (mData != nullptr && mData->mIsCreated && mData->mPtr != nullptr);
19
20 if (checkDependencies && isLoaded)
21 isLoaded = mData->mPtr->areDependenciesLoaded();
22
23 return isLoaded;
24 }
25
26 void ResourceHandleBase::blockUntilLoaded(bool waitForDependencies) const
27 {
28 if(mData == nullptr)
29 return;
30
31 if (!mData->mIsCreated)
32 {
33 Lock lock(mResourceCreatedMutex);
34 while (!mData->mIsCreated)
35 {
36 mResourceCreatedCondition.wait(lock);
37 }
38
39 // Send out ResourceListener events right away, as whatever called this method probably also expects the
40 // listener events to trigger immediately as well
41 if(BS_THREAD_CURRENT_ID == gCoreApplication().getSimThreadId())
42 ResourceListenerManager::instance().notifyListeners(mData->mUUID);
43 }
44
45 if (waitForDependencies)
46 {
47 bs_frame_mark();
48
49 {
50 FrameVector<HResource> dependencies;
51 mData->mPtr->getResourceDependencies(dependencies);
52
53 for (auto& dependency : dependencies)
54 dependency.blockUntilLoaded(waitForDependencies);
55 }
56
57 bs_frame_clear();
58 }
59 }
60
61 void ResourceHandleBase::release()
62 {
63 gResources().release(*this);
64 }
65
66 void ResourceHandleBase::destroy()
67 {
68 if(mData->mPtr)
69 gResources().destroy(*this);
70 }
71
72 void ResourceHandleBase::setHandleData(const SPtr<Resource>& ptr, const UUID& uuid)
73 {
74 mData->mPtr = ptr;
75
76 if(mData->mPtr)
77 mData->mUUID = uuid;
78 }
79
80 void ResourceHandleBase::notifyLoadComplete()
81 {
82 if (!mData->mIsCreated)
83 {
84 Lock lock(mResourceCreatedMutex);
85 {
86 mData->mIsCreated = true;
87 }
88
89 mResourceCreatedCondition.notify_all();
90 }
91 }
92
93 void ResourceHandleBase::clearHandleData()
94 {
95 mData->mPtr = nullptr;
96
97 Lock lock(mResourceCreatedMutex);
98 mData->mIsCreated = false;
99 }
100
101 void ResourceHandleBase::addInternalRef()
102 {
103 mData->mRefCount.fetch_add(1, std::memory_order_relaxed);
104 }
105
106 void ResourceHandleBase::removeInternalRef()
107 {
108 mData->mRefCount.fetch_sub(1, std::memory_order_relaxed);
109 }
110
111 void ResourceHandleBase::throwIfNotLoaded() const
112 {
113#if BS_DEBUG_MODE
114 if (!isLoaded(false))
115 {
116 BS_EXCEPT(InternalErrorException, "Trying to access a resource that hasn't been loaded yet.");
117 }
118#endif
119 }
120
121 RTTITypeBase* TResourceHandleBase<true>::getRTTIStatic()
122 {
123 return WeakResourceHandleRTTI::instance();
124 }
125
126 RTTITypeBase* TResourceHandleBase<true>::getRTTI() const
127 {
128 return getRTTIStatic();
129 }
130
131 RTTITypeBase* TResourceHandleBase<false>::getRTTIStatic()
132 {
133 return ResourceHandleRTTI::instance();
134 }
135
136 RTTITypeBase* TResourceHandleBase<false>::getRTTI() const
137 {
138 return getRTTIStatic();
139 }
140}
141