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 | |
11 | namespace 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 |