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