aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Maps/MapManager.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-06-05 19:25:42 +0200
committerCarbenium <carbenium@outlook.com>2020-07-16 21:47:27 +0200
commitfbdf8784a5c03dfcb575ef7b760a62d0d9d2acc1 (patch)
tree481382d77cf0f3794f1b9b9d9032db98e9fcd988 /src/server/game/Maps/MapManager.cpp
parentf4ac8146b6fb76fd80f525dbb8b14706fa080f98 (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.cpp63
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;
}