-
-
Notifications
You must be signed in to change notification settings - Fork 502
Make single link node pool unlimited #3986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Dutchman101
merged 20 commits into
multitheftauto:master
from
TheNormalnij:TheNormalnij/single_node_pool_resize
Feb 6, 2025
Merged
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
c5c9c74
Unlimited CPtrNodeSingleListSA
TheNormalnij 31c5d72
Remove old pool
TheNormalnij 53ad82a
Merge branch 'master' into TheNormalnij/single_node_pool_resize
TheNormalnij 36f88bc
Add engineSetPoolCapacity support
TheNormalnij 2ddc8dc
don not call destructor
TheNormalnij 463d400
Fix crash
TheNormalnij f9c39b0
Merge branch 'master' into TheNormalnij/single_node_pool_resize
TheNormalnij abee415
Reset capacity after disconnect
TheNormalnij 5454969
Remove old hacks
TheNormalnij cf75844
Fix crash on reconnect
TheNormalnij fc7eaf2
Fix warning
TheNormalnij 749c4c9
use free indexes stack
TheNormalnij dcce3ab
Merge branch 'master' into TheNormalnij/single_node_pool_resize
TheNormalnij 4d9bb15
Rename m_unusedIndexes -> m_unusedIndices
TheNormalnij 9db10d5
GrownStrategy -> GrowStrategy
TheNormalnij d4986ea
PoolGrownByHalfStrategy -> PoolGrownAddStrategy
TheNormalnij 74cb8c4
PoolGrownAddStrategy -> PoolGrowAddStrategy
TheNormalnij db10972
Handle exception
TheNormalnij bca3619
Use assert for RemoveItem
TheNormalnij ec66b96
std::vector<std::unique_ptr<>> -> std::list
TheNormalnij File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| /***************************************************************************** | ||
| * | ||
| * PROJECT: Multi Theft Auto v1.0 | ||
| * LICENSE: See LICENSE in the top level directory | ||
| * FILE: game_sa/CDynamicPool.h | ||
| * PURPOSE: Custom implementation for SA pools | ||
| * | ||
| * Multi Theft Auto is available from http://www.multitheftauto.com/ | ||
| * | ||
| *****************************************************************************/ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <vector> | ||
| #include <array> | ||
| #include <memory> | ||
|
|
||
| template <typename PoolObjT> | ||
| class CDynamicPoolPart | ||
| { | ||
| public: | ||
| explicit CDynamicPoolPart(std::size_t size) : m_size{size}, m_usedSize{0}, m_lastFreeSlot{0} | ||
| { | ||
| m_items = std::make_unique<PoolObjT[]>(size); | ||
| m_usedSlots = std::make_unique<bool[]>(size); | ||
| } | ||
|
|
||
| PoolObjT* AllocateItem() | ||
| { | ||
| bool flipped = false; | ||
| while (true) | ||
| { | ||
| if (m_usedSlots[m_lastFreeSlot]) | ||
| { | ||
| m_lastFreeSlot++; | ||
| if (m_lastFreeSlot >= m_size) | ||
| { | ||
| if (flipped) | ||
| return nullptr; | ||
| m_lastFreeSlot = 0; | ||
| flipped = true; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| m_usedSlots[m_lastFreeSlot] = true; | ||
| m_usedSize++; | ||
| return &m_items[m_lastFreeSlot]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void RemoveItem(PoolObjT* item) | ||
| { | ||
| auto pos = item - m_items.get(); | ||
| assert(m_usedSlots[pos], "Invalid item for CDynamicPoolPart::RemoveItem"); | ||
|
|
||
| m_usedSlots[pos] = false; | ||
| m_usedSize--; | ||
| } | ||
|
|
||
| bool OwnsItem(PoolObjT* item) const noexcept { return item >= m_items.get() && item < m_items.get() + m_size; } | ||
| bool HasFreeSize() const noexcept { return m_size != m_usedSize; } | ||
| std::size_t GetCapacity() const noexcept { return m_size; } | ||
| std::size_t GetUsedSize() const noexcept { return m_usedSize; } | ||
|
|
||
| private: | ||
| std::unique_ptr<PoolObjT[]> m_items; | ||
| std::unique_ptr<bool[]> m_usedSlots; | ||
| const std::size_t m_size; | ||
| std::size_t m_usedSize; | ||
| std::size_t m_lastFreeSlot; | ||
| }; | ||
|
|
||
| template <std::size_t InitialSize> | ||
| struct PoolGrownByHalfStrategy | ||
| { | ||
| static constexpr std::size_t GetInitialSize() { return InitialSize; } | ||
| static constexpr std::size_t GetNextSize(std::size_t index) { return InitialSize / 2; } | ||
| }; | ||
|
|
||
| template <typename PoolObjT, typename GrownStrategy> | ||
TheNormalnij marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| class CDynamicPool | ||
| { | ||
| public: | ||
| CDynamicPool() | ||
| { | ||
| constexpr size_t initialSize = GrownStrategy::GetInitialSize(); | ||
| m_poolParts.emplace_back(std::make_unique<CDynamicPoolPart<PoolObjT>>(initialSize)); | ||
| } | ||
|
|
||
| PoolObjT* AllocateItem() | ||
| { | ||
| for (auto& pool : m_poolParts) | ||
| { | ||
| if (pool->HasFreeSize()) | ||
| return pool->AllocateItem(); | ||
| } | ||
|
|
||
| return AllocateNewPart()->AllocateItem(); | ||
TheNormalnij marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| void RemoveItem(PoolObjT* item) | ||
| { | ||
| for (auto& pool : m_poolParts) | ||
| { | ||
| if (pool->OwnsItem(item)) | ||
| { | ||
| pool->RemoveItem(item); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| throw std::exception("Invalid item for CDynamicPool::RemoveItem"); | ||
| } | ||
|
|
||
| std::size_t GetCapacity() const noexcept | ||
| { | ||
| std::size_t size = 0; | ||
| for (auto& pool : m_poolParts) | ||
| size += pool->GetCapacity(); | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| std::size_t GetUsedSize() const noexcept | ||
| { | ||
| std::size_t size = 0; | ||
| for (auto& pool : m_poolParts) | ||
| size += pool->GetUsedSize(); | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| bool SetCapacity(std::size_t newSize) { | ||
| if (newSize == 0) | ||
| return false; | ||
|
|
||
| std::size_t currentSize = GetCapacity(); | ||
|
|
||
| if (currentSize == newSize) | ||
| return false; | ||
| else if (currentSize < newSize) | ||
| { | ||
| // Grown | ||
| while (currentSize < newSize) | ||
| { | ||
| try | ||
| { | ||
| auto* nextPart = AllocateNewPart(); | ||
| currentSize += nextPart->GetCapacity(); | ||
| } | ||
| catch (const std::bad_alloc& ex) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // Shrink | ||
| while (true) | ||
| { | ||
| auto* part = m_poolParts.back().get(); | ||
| if (part->GetUsedSize() != 0) | ||
| return false; | ||
|
|
||
| currentSize -= part->GetCapacity(); | ||
| if (currentSize < newSize) | ||
| return false; | ||
|
|
||
| m_poolParts.pop_back(); | ||
|
|
||
| if (currentSize == newSize) | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| private: | ||
| CDynamicPoolPart<PoolObjT>* AllocateNewPart() | ||
| { | ||
| const std::size_t nextSize = GrownStrategy::GetNextSize(m_poolParts.size()); | ||
| m_poolParts.emplace_back(std::make_unique<CDynamicPoolPart<PoolObjT>>(nextSize)); | ||
TheNormalnij marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return m_poolParts.back().get(); | ||
| } | ||
|
|
||
| private: | ||
| std::vector<std::unique_ptr<CDynamicPoolPart<PoolObjT>>> m_poolParts; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /***************************************************************************** | ||
| * | ||
| * PROJECT: Multi Theft Auto v1.0 | ||
| * LICENSE: See LICENSE in the top level directory | ||
| * FILE: game_sa/CPtrNodeSingleLinkPoolSA.cpp | ||
| * PURPOSE: Custom implementation for the CPtrNodeSingleLinkPool pool | ||
| * | ||
| * Multi Theft Auto is available from http://www.multitheftauto.com/ | ||
| * | ||
| *****************************************************************************/ | ||
|
|
||
| #include "StdInc.h" | ||
| #include "CPtrNodeSingleLinkPoolSA.h" | ||
|
|
||
| CPtrNodeSingleLinkPoolSA::pool_t* CPtrNodeSingleLinkPoolSA::m_customPool = nullptr; | ||
|
|
||
| CPtrNodeSingleLinkPoolSA::CPtrNodeSingleLinkPoolSA() | ||
| { | ||
| if (!m_customPool) | ||
| m_customPool = new CPtrNodeSingleLinkPoolSA::pool_t(); | ||
| } | ||
|
|
||
| constexpr std::uint32_t HOOKPOS_SingleLinkNodeConstructor = 0x552380; | ||
| constexpr std::size_t HOOKSIZE_SingleLinkNodeConstructor = 6; | ||
| static CPtrNodeSingleLinkPoolSA::pool_item_t* __cdecl HOOK_SingleLinkNodeConstructor() | ||
| { | ||
| return CPtrNodeSingleLinkPoolSA::GetPoolInstance()->AllocateItem(); | ||
| } | ||
|
|
||
| constexpr std::uint32_t HOOKPOS_SingleLinkNodeDestructor = 0x552390; | ||
| constexpr std::size_t HOOKSIZE_SingleLinkNodeDestructor = 6; | ||
| static CPtrNodeSingleLinkPoolSA::pool_item_t* __cdecl HOOK_SingleLinkNodeDestructor(CPtrNodeSingleLinkPoolSA::pool_item_t* item) | ||
| { | ||
| CPtrNodeSingleLinkPoolSA::GetPoolInstance()->RemoveItem(item); | ||
| // The game doesen't use the return value | ||
| return item; | ||
| } | ||
|
|
||
| void CPtrNodeSingleLinkPoolSA::StaticSetHooks() | ||
| { | ||
| EZHookInstall(SingleLinkNodeConstructor); | ||
| EZHookInstall(SingleLinkNodeDestructor); | ||
|
|
||
| // Skip the original pool initialization | ||
| MemCpy((void*)0x550F26, "\xEB\x2D", 2); | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /***************************************************************************** | ||
| * | ||
| * PROJECT: Multi Theft Auto v1.0 | ||
| * LICENSE: See LICENSE in the top level directory | ||
| * FILE: game_sa/CPtrNodeSingleLinkPoolSA.h | ||
| * PURPOSE: Custom implementation for the CPtrNodeSingleLinkPool pool | ||
| * | ||
| * Multi Theft Auto is available from http://www.multitheftauto.com/ | ||
| * | ||
| *****************************************************************************/ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "CPoolSAInterface.h" | ||
| #include "CDynamicPool.h" | ||
| #include "CPtrNodeSingleListSA.h" | ||
| #include <game/CPtrNodeSingleLinkPool.h> | ||
|
|
||
| class CPtrNodeSingleLinkPoolSA final : public CPtrNodeSingleLinkPool | ||
| { | ||
| public: | ||
| using pool_item_t = CPtrNodeSingleLink<void*>; | ||
| using pool_t = CDynamicPool<pool_item_t, PoolGrownByHalfStrategy<MAX_POINTER_SINGLE_LINKS>>; | ||
|
|
||
| CPtrNodeSingleLinkPoolSA(); | ||
|
|
||
| std::size_t GetCapacity() const override { return m_customPool->GetCapacity(); } | ||
| std::size_t GetUsedSize() const override { return m_customPool->GetUsedSize(); } | ||
|
|
||
| bool Resize(std::size_t newSize) override { return m_customPool->SetCapacity(newSize); }; | ||
|
|
||
| static auto* GetPoolInstance() { return m_customPool; } | ||
| static void StaticSetHooks(); | ||
| private: | ||
| static pool_t* m_customPool; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /***************************************************************************** | ||
| * | ||
| * PROJECT: Multi Theft Auto | ||
| * LICENSE: See LICENSE in the top level directory | ||
| * FILE: sdk/game/CPtrNodeSingleLinkPool.h | ||
| * | ||
| * Multi Theft Auto is available from http://www.multitheftauto.com/ | ||
| * | ||
| *****************************************************************************/ | ||
|
|
||
| #pragma once | ||
|
|
||
| class CPtrNodeSingleLinkPool | ||
| { | ||
| public: | ||
| virtual bool Resize(std::size_t size) = 0; | ||
| virtual std::size_t GetCapacity() const = 0; | ||
| virtual std::size_t GetUsedSize() const = 0; | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.