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 | #pragma once |
4 | |
5 | #include "BsCorePrerequisites.h" |
6 | #include "CoreThread/BsCoreObjectCore.h" |
7 | #include "Utility/BsModule.h" |
8 | |
9 | namespace bs |
10 | { |
11 | /** @addtogroup CoreThread-Internal |
12 | * @{ |
13 | */ |
14 | |
15 | // TODO Low priority - Add debug option that would remember a call stack for each resource initialization, |
16 | // so when we fail to release one we know which one it is. |
17 | |
18 | /** |
19 | * Manager that keeps track of all active CoreObject%s. |
20 | * |
21 | * @note Internal class. |
22 | * @note Thread safe unless specified otherwise. |
23 | */ |
24 | class BS_CORE_EXPORT CoreObjectManager : public Module<CoreObjectManager> |
25 | { |
26 | /** |
27 | * Stores dirty data that is to be transferred from sim thread to core thread part of a CoreObject, for a single |
28 | * object. |
29 | */ |
30 | struct CoreStoredSyncObjData |
31 | { |
32 | CoreStoredSyncObjData() |
33 | :internalId(0) |
34 | { } |
35 | |
36 | CoreStoredSyncObjData(const SPtr<ct::CoreObject> destObj, UINT64 internalId, const CoreSyncData& syncData) |
37 | :destinationObj(destObj), syncData(syncData), internalId(internalId) |
38 | { } |
39 | |
40 | SPtr<ct::CoreObject> destinationObj; |
41 | CoreSyncData syncData; |
42 | UINT64 internalId; |
43 | }; |
44 | |
45 | /** |
46 | * Stores dirty data that is to be transferred from sim thread to core thread part of a CoreObject, for all dirty |
47 | * objects in one frame. |
48 | */ |
49 | struct CoreStoredSyncData |
50 | { |
51 | FrameAlloc* alloc = nullptr; |
52 | Vector<CoreStoredSyncObjData> entries; |
53 | Vector<SPtr<ct::CoreObject>> destroyedObjects; |
54 | }; |
55 | |
56 | /** Contains information about a dirty CoreObject that requires syncing to the core thread. */ |
57 | struct DirtyObjectData |
58 | { |
59 | CoreObject* object; |
60 | INT32 syncDataId; |
61 | }; |
62 | |
63 | public: |
64 | CoreObjectManager(); |
65 | ~CoreObjectManager(); |
66 | |
67 | /** Generates a new unique ID for a core object. */ |
68 | UINT64 generateId(); |
69 | |
70 | /** Registers a new CoreObject notifying the manager the object is created. */ |
71 | void registerObject(CoreObject* object); |
72 | |
73 | /** Unregisters a CoreObject notifying the manager the object is destroyed. */ |
74 | void unregisterObject(CoreObject* object); |
75 | |
76 | /** Notifies the system that a CoreObject is dirty and needs to be synced with the core thread. */ |
77 | void notifyCoreDirty(CoreObject* object); |
78 | |
79 | /** Notifies the system that CoreObject dependencies are dirty and should be updated. */ |
80 | void notifyDependenciesDirty(CoreObject* object); |
81 | |
82 | /** |
83 | * Synchronizes all dirty CoreObjects with the core thread. Their dirty data will be allocated using the global |
84 | * frame allocator and then queued for update using the core thread queue for the calling thread. |
85 | * |
86 | * @note Sim thread only. |
87 | * @note This is an @ref asyncMethod "asynchronous method". |
88 | */ |
89 | void syncToCore(); |
90 | |
91 | /** |
92 | * Synchronizes an individual dirty CoreObject with the core thread. Its dirty data will be allocated using the |
93 | * global frame allocator and then queued for update the core thread queue for the calling thread. |
94 | * |
95 | * @note Sim thread only. |
96 | * @note This is an @ref asyncMethod "asynchronous method". |
97 | */ |
98 | void syncToCore(CoreObject* object); |
99 | |
100 | private: |
101 | /** |
102 | * Stores all syncable data from dirty core objects into memory allocated by the provided allocator. Additional |
103 | * meta-data is stored internally to be used by call to syncUpload(). |
104 | * |
105 | * @param[in] allocator Allocator to use for allocating memory for stored data. |
106 | * |
107 | * @note Sim thread only. |
108 | * @note Must be followed by a call to syncUpload() with the same type. |
109 | */ |
110 | void syncDownload(FrameAlloc* allocator); |
111 | |
112 | /** |
113 | * Copies all the data stored by previous call to syncDownload() into core thread versions of CoreObjects. |
114 | * |
115 | * @note Core thread only. |
116 | * @note Must be preceded by a call to syncDownload(). |
117 | */ |
118 | void syncUpload(); |
119 | |
120 | /** |
121 | * Updates the cached list of dependencies and dependants for the specified object. |
122 | * |
123 | * @param[in] object Update to update dependencies for. |
124 | * @param[in] dependencies New set of dependencies, or null to clear all dependencies. |
125 | */ |
126 | void updateDependencies(CoreObject* object, Vector<CoreObject*>* dependencies); |
127 | |
128 | UINT64 mNextAvailableID; |
129 | Map<UINT64, CoreObject*> mObjects; |
130 | Map<UINT64, DirtyObjectData> mDirtyObjects; |
131 | Map<UINT64, Vector<CoreObject*>> mDependencies; |
132 | Map<UINT64, Vector<CoreObject*>> mDependants; |
133 | |
134 | Vector<CoreStoredSyncObjData> mDestroyedSyncData; |
135 | List<CoreStoredSyncData> mCoreSyncData; |
136 | |
137 | Mutex mObjectsMutex; |
138 | }; |
139 | |
140 | /** @} */ |
141 | } |
142 | |
143 | |