From 89fe996a34bc588367c57168849ac0e9a2d65cdd Mon Sep 17 00:00:00 2001 From: powerof3 <32599957+powerof3@users.noreply.github.com> Date: Wed, 22 Nov 2023 07:30:57 +0530 Subject: [PATCH] feat: add `BSGuarded` (#223) --- CommonLibSF/include/RE/B/BGSInventoryItem.h | 2 +- CommonLibSF/include/RE/B/BSLock.h | 47 +++++++++++++++++++++ CommonLibSF/include/RE/T/TESObjectREFR.h | 20 ++++----- CommonLibSF/src/RE/T/TESObjectREFR.cpp | 5 +-- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/CommonLibSF/include/RE/B/BGSInventoryItem.h b/CommonLibSF/include/RE/B/BGSInventoryItem.h index 72e42ad9..f5c598d2 100644 --- a/CommonLibSF/include/RE/B/BGSInventoryItem.h +++ b/CommonLibSF/include/RE/B/BGSInventoryItem.h @@ -17,7 +17,7 @@ namespace RE public: // members BSTSmartPointer extra; // 00 - std::uint32_t unk10; // 10 + std::uint32_t count; // 10 }; static_assert(sizeof(Stack) == 0x10); diff --git a/CommonLibSF/include/RE/B/BSLock.h b/CommonLibSF/include/RE/B/BSLock.h index 57ca3a27..e0b5268e 100644 --- a/CommonLibSF/include/RE/B/BSLock.h +++ b/CommonLibSF/include/RE/B/BSLock.h @@ -116,4 +116,51 @@ namespace RE using BSAutoWriteLock = BSAutoLock; static_assert(sizeof(BSAutoWriteLock) == 0x8); + + template + class BSGuarded + { + public: + template class Policy = BSAutoLockDefaultPolicy> + class Guard + { + public: + explicit Guard(U& a_data, Mutex& a_mutex) : + _guard(a_mutex), + _data(a_data) + {} + + U& operator*() { return _data; } + U& operator->() { return _data; } + const U& operator*() const { return _data; } + const U& operator->() const { return _data; } + + private: + // members + BSAutoLock _guard{}; // 0 - Lock guard is first here? + U& _data; // 8 + }; + + auto lock() + { + return Guard(_data, _lock); + } + + auto lock_read() const + requires std::is_same_v + { + return Guard(_data, _lock); + } + + auto lock_write() + requires std::is_same_v + { + return Guard(_data, _lock); + } + + private: + // members + T _data{}; // ?? + mutable Mutex _lock{}; // ?? + }; } diff --git a/CommonLibSF/include/RE/T/TESObjectREFR.h b/CommonLibSF/include/RE/T/TESObjectREFR.h index 743cf859..a3dc8ad7 100644 --- a/CommonLibSF/include/RE/T/TESObjectREFR.h +++ b/CommonLibSF/include/RE/T/TESObjectREFR.h @@ -386,17 +386,15 @@ namespace RE void Unlock(); // members - OBJ_REFR data; // 0A0 - BGSInventoryList* inventoryList; // 0D0 - this + lock is one struct? - mutable BSReadWriteLock inventoryListLock; // 0D8 - TESObjectCELL* parentCell; // 0E0 - LOADED_REF_DATA* loadedData; // 0E8 - same as above - mutable BSReadWriteLock loadedDataLock; // 0F0 - BSTSmartPointer extraDataList; // 0F8 - BGSLocalizedString unk100; // 100 - empty? - std::uint16_t scale; // 108 - bool unk10A; // 10A - std::uint8_t flags; // 10B + OBJ_REFR data; // 0A0 + BSGuarded inventoryList; // 0D0 + TESObjectCELL* parentCell; // 0E0 + BSGuarded loadedData; // 0E8 + BSTSmartPointer extraDataList; // 0F8 + BGSLocalizedString unk100; // 100 - empty? + std::uint16_t scale; // 108 + std::uint8_t unk10A; // 10A + std::uint8_t flags; // 10B private: void AddLockChange(); diff --git a/CommonLibSF/src/RE/T/TESObjectREFR.cpp b/CommonLibSF/src/RE/T/TESObjectREFR.cpp index c44aed8b..5fd3a3c1 100644 --- a/CommonLibSF/src/RE/T/TESObjectREFR.cpp +++ b/CommonLibSF/src/RE/T/TESObjectREFR.cpp @@ -21,9 +21,8 @@ namespace RE void TESObjectREFR::ForEachInventoryItem(std::function a_callback) const { - BSAutoReadLock locker(inventoryListLock); - if (inventoryList) { - for (const auto& invItem : inventoryList->data) { + if (const auto invList = inventoryList.lock_read(); *invList) { + for (const auto& invItem : invList->data) { if (invItem.object && a_callback(invItem) == BSContainer::ForEachResult::kStop) { break; }