diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-06-05 19:25:42 +0200 |
---|---|---|
committer | Carbenium <carbenium@outlook.com> | 2020-07-16 21:47:27 +0200 |
commit | fbdf8784a5c03dfcb575ef7b760a62d0d9d2acc1 (patch) | |
tree | 481382d77cf0f3794f1b9b9d9032db98e9fcd988 /src/server/game/Maps/MapManager.cpp | |
parent | f4ac8146b6fb76fd80f525dbb8b14706fa080f98 (diff) |
Core/Instances: Fixed and optimized instance id reuse
(cherry picked from commit 2639056071597edfdf74b31a16ce644610a1b6d9)
Diffstat (limited to 'src/server/game/Maps/MapManager.cpp')
-rw-r--r-- | src/server/game/Maps/MapManager.cpp | 63 |
1 files changed, 27 insertions, 36 deletions
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index 6a441a21f9f..4125b574b83 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -337,55 +337,48 @@ void MapManager::InitInstanceIds() { _nextInstanceId = 1; - QueryResult result = CharacterDatabase.Query("SELECT MAX(id) FROM instance"); - if (result) - { - uint32 maxId = (*result)[0].GetUInt32(); + if (QueryResult result = CharacterDatabase.Query("SELECT IFNULL(MAX(id), 0) FROM instance")) + _freeInstanceIds.resize((*result)[0].GetUInt32() + 2, true); // make space for one extra to be able to access [_nextInstanceId] index in case all slots are taken + else + _freeInstanceIds.resize(_nextInstanceId + 1, true); - // Resize to multiples of 32 (vector<bool> allocates memory the same way) - _instanceIds.resize((maxId / 32) * 32 + (maxId % 32 > 0 ? 32 : 0)); - } + // never allow 0 id + _freeInstanceIds[0] = false; } void MapManager::RegisterInstanceId(uint32 instanceId) { // Allocation and sizing was done in InitInstanceIds() - _instanceIds[instanceId] = true; + _freeInstanceIds[instanceId] = false; + + // Instances are pulled in ascending order from db and nextInstanceId is initialized with 1, + // so if the instance id is used, increment until we find the first unused one for a potential new instance + if (_nextInstanceId == instanceId) + ++_nextInstanceId; } uint32 MapManager::GenerateInstanceId() { - uint32 newInstanceId = _nextInstanceId; - - // Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId() - for (uint32 i = ++_nextInstanceId; i < 0xFFFFFFFF; ++i) - { - if ((i < _instanceIds.size() && !_instanceIds[i]) || i >= _instanceIds.size()) - { - _nextInstanceId = i; - break; - } - } - - if (newInstanceId == _nextInstanceId) + if (_nextInstanceId == 0xFFFFFFFF) { TC_LOG_ERROR("maps", "Instance ID overflow!! Can't continue, shutting down server. "); World::StopNow(ERROR_EXIT_CODE); + return _nextInstanceId; } - // Allocate space if necessary - if (newInstanceId >= uint32(_instanceIds.size())) + uint32 newInstanceId = _nextInstanceId; + ASSERT(newInstanceId < _freeInstanceIds.size()); + _freeInstanceIds[newInstanceId] = false; + + // Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId() + size_t nextFreedId = _freeInstanceIds.find_next(_nextInstanceId++); + if (nextFreedId == InstanceIds::npos) { - // Due to the odd memory allocation behavior of vector<bool> we match size to capacity before triggering a new allocation - if (_instanceIds.size() < _instanceIds.capacity()) - { - _instanceIds.resize(_instanceIds.capacity()); - } - else - _instanceIds.resize((newInstanceId / 32) * 32 + (newInstanceId % 32 > 0 ? 32 : 0)); + _nextInstanceId = uint32(_freeInstanceIds.size()); + _freeInstanceIds.push_back(true); } - - _instanceIds[newInstanceId] = true; + else + _nextInstanceId = uint32(nextFreedId); return newInstanceId; } @@ -393,8 +386,6 @@ uint32 MapManager::GenerateInstanceId() void MapManager::FreeInstanceId(uint32 instanceId) { // If freed instance id is lower than the next id available for new instances, use the freed one instead - if (instanceId < _nextInstanceId) - SetNextInstanceId(instanceId); - - _instanceIds[instanceId] = false; + _nextInstanceId = std::min(instanceId, _nextInstanceId); + _freeInstanceIds[instanceId] = true; } |