From bc6013ab709804f9d3ffb850c6137ec9049b6f58 Mon Sep 17 00:00:00 2001 From: MatthewBeshay <92357869+MatthewBeshay@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:45:55 +1100 Subject: [PATCH] Replace all CRITICAL_SECTION usage with std::mutex and std::lock_guard Migrates 59 files from WinAPI CRITICAL_SECTION to portable C++ std::mutex/std::lock_guard/std::unique_lock. Removes Linux CRITICAL_SECTION shims from winapi_stubs.h. --- Minecraft.Client/Level/MultiPlayerLevel.cpp | 142 ++++++------- Minecraft.Client/Level/ServerLevel.cpp | 194 +++++++----------- Minecraft.Client/Level/ServerLevel.h | 9 +- Minecraft.Client/Minecraft.cpp | 9 +- Minecraft.Client/Minecraft.h | 3 +- Minecraft.Client/MinecraftServer.cpp | 71 +++---- Minecraft.Client/MinecraftServer.h | 3 +- .../Network/MultiPlayerChunkCache.cpp | 19 +- .../Network/MultiPlayerChunkCache.h | 3 +- Minecraft.Client/Network/PlayerConnection.cpp | 10 +- Minecraft.Client/Network/PlayerConnection.h | 3 +- Minecraft.Client/Network/PlayerList.cpp | 20 +- Minecraft.Client/Network/PlayerList.h | 5 +- Minecraft.Client/Network/ServerChunkCache.cpp | 20 +- Minecraft.Client/Network/ServerChunkCache.h | 3 +- Minecraft.Client/Network/ServerConnection.cpp | 22 +- Minecraft.Client/Network/ServerConnection.h | 3 +- .../Platform/Common/C4JMemoryPool.h | 6 - .../Platform/Common/Consoles_App.cpp | 118 ++++------- .../Platform/Common/Consoles_App.h | 17 +- .../Leaderboards/SonyLeaderboardManager.cpp | 27 ++- .../Leaderboards/SonyLeaderboardManager.h | 3 +- .../Common/UI/UIComponent_Panorama.cpp | 30 +-- .../Platform/Common/UI/UIController.cpp | 71 +++---- .../Platform/Common/UI/UIController.h | 9 +- .../Platform/Common/UI/UIScene.cpp | 12 +- .../Platform/Linux/Linux_Minecraft.cpp | 81 ++++---- .../Platform/Linux/Stubs/winapi_stubs.h | 40 ---- .../Windows64/Windows64_Minecraft.cpp | 81 ++++---- Minecraft.Client/Rendering/Chunk.cpp | 91 ++++---- Minecraft.Client/Rendering/Chunk.h | 4 +- .../EntityRenderers/ProgressRenderer.cpp | 69 ++++--- .../EntityRenderers/ProgressRenderer.h | 3 +- Minecraft.Client/Rendering/GameRenderer.cpp | 47 ++--- Minecraft.Client/Rendering/GameRenderer.h | 3 +- Minecraft.Client/Rendering/LevelRenderer.cpp | 105 ++++------ Minecraft.Client/Rendering/LevelRenderer.h | 9 +- .../IO/Files/ConsoleSaveFileOriginal.cpp | 4 +- .../IO/Files/ConsoleSaveFileOriginal.h | 3 +- .../IO/Files/ConsoleSaveFileSplit.cpp | 6 +- .../IO/Files/ConsoleSaveFileSplit.h | 3 +- Minecraft.World/IO/Streams/Compression.cpp | 21 +- Minecraft.World/IO/Streams/Compression.h | 5 +- Minecraft.World/Level/Level.cpp | 83 ++++---- Minecraft.World/Level/Level.h | 7 +- Minecraft.World/Level/LevelChunk.cpp | 127 +++++------- Minecraft.World/Level/LevelChunk.h | 8 +- .../Level/Storage/CompressedTileStorage.cpp | 26 +-- .../Level/Storage/CompressedTileStorage.h | 3 +- .../Level/Storage/McRegionChunkStorage.cpp | 63 +++--- .../Level/Storage/McRegionChunkStorage.h | 4 +- .../Level/Storage/OldChunkStorage.cpp | 34 ++- .../Level/Storage/ZonedChunkStorage.cpp | 32 ++- Minecraft.World/Network/Connection.cpp | 127 ++++++------ Minecraft.World/Network/Connection.h | 8 +- Minecraft.World/Network/Socket.cpp | 134 ++++++------ Minecraft.World/Network/Socket.h | 5 +- .../WorldGen/Biomes/BiomeCache.cpp | 9 +- Minecraft.World/WorldGen/Biomes/BiomeCache.h | 3 +- 59 files changed, 952 insertions(+), 1128 deletions(-) diff --git a/Minecraft.Client/Level/MultiPlayerLevel.cpp b/Minecraft.Client/Level/MultiPlayerLevel.cpp index a34ba8ec5..69315def1 100644 --- a/Minecraft.Client/Level/MultiPlayerLevel.cpp +++ b/Minecraft.Client/Level/MultiPlayerLevel.cpp @@ -1,4 +1,5 @@ #include "../Platform/stdafx.h" +#include #include "MultiPlayerLevel.h" #include "../Player/MultiPlayerLocalPlayer.h" #include "../Network/ClientConnection.h" @@ -117,14 +118,15 @@ void MultiPlayerLevel::tick() { PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Entity re-entry"); - EnterCriticalSection(&m_entitiesCS); - for (int i = 0; i < 10 && !reEntries.empty(); i++) { - std::shared_ptr e = *(reEntries.begin()); + { + std::lock_guard lock(m_entitiesCS); + for (int i = 0; i < 10 && !reEntries.empty(); i++) { + std::shared_ptr e = *(reEntries.begin()); - if (find(entities.begin(), entities.end(), e) == entities.end()) - addEntity(e); + if (find(entities.begin(), entities.end(), e) == entities.end()) + addEntity(e); + } } - LeaveCriticalSection(&m_entitiesCS); PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Connection ticking"); @@ -808,23 +810,24 @@ void MultiPlayerLevel::setDayTime(int64_t newTime) { void MultiPlayerLevel::removeAllPendingEntityRemovals() { // entities.removeAll(entitiesToRemove); - EnterCriticalSection(&m_entitiesCS); - for (auto it = entities.begin(); it != entities.end();) { - bool found = false; - for (auto it2 = entitiesToRemove.begin(); - it2 != entitiesToRemove.end(); it2++) { - if ((*it) == (*it2)) { - found = true; - break; + { + std::lock_guard lock(m_entitiesCS); + for (auto it = entities.begin(); it != entities.end();) { + bool found = false; + for (auto it2 = entitiesToRemove.begin(); + it2 != entitiesToRemove.end(); it2++) { + if ((*it) == (*it2)) { + found = true; + break; + } + } + if (found) { + it = entities.erase(it); + } else { + it++; } } - if (found) { - it = entities.erase(it); - } else { - it++; - } } - LeaveCriticalSection(&m_entitiesCS); auto endIt = entitiesToRemove.end(); for (auto it = entitiesToRemove.begin(); it != endIt; it++) { @@ -845,36 +848,37 @@ void MultiPlayerLevel::removeAllPendingEntityRemovals() { entitiesToRemove.clear(); // for (int i = 0; i < entities.size(); i++) - EnterCriticalSection(&m_entitiesCS); - std::vector >::iterator it = entities.begin(); - while (it != entities.end()) { - std::shared_ptr e = *it; // entities.at(i); + { + std::lock_guard lock(m_entitiesCS); + std::vector >::iterator it = entities.begin(); + while (it != entities.end()) { + std::shared_ptr e = *it; // entities.at(i); - if (e->riding != nullptr) { - if (e->riding->removed || e->riding->rider.lock() != e) { - e->riding->rider = std::weak_ptr(); - e->riding = nullptr; + if (e->riding != nullptr) { + if (e->riding->removed || e->riding->rider.lock() != e) { + e->riding->rider = std::weak_ptr(); + e->riding = nullptr; + } else { + ++it; + continue; + } + } + + if (e->removed) { + int xc = e->xChunk; + int zc = e->zChunk; + if (e->inChunk && hasChunk(xc, zc)) { + getChunk(xc, zc)->removeEntity(e); + } + // entities.remove(i--); + + it = entities.erase(it); + entityRemoved(e); } else { - ++it; - continue; + it++; } } - - if (e->removed) { - int xc = e->xChunk; - int zc = e->zChunk; - if (e->inChunk && hasChunk(xc, zc)) { - getChunk(xc, zc)->removeEntity(e); - } - // entities.remove(i--); - - it = entities.erase(it); - entityRemoved(e); - } else { - it++; - } } - LeaveCriticalSection(&m_entitiesCS); } void MultiPlayerLevel::removeClientConnection(ClientConnection* c, @@ -907,34 +911,34 @@ void MultiPlayerLevel::dataReceivedForChunk(int x, int z) { void MultiPlayerLevel::removeUnusedTileEntitiesInRegion(int x0, int y0, int z0, int x1, int y1, int z1) { - EnterCriticalSection(&m_tileEntityListCS); + { + std::lock_guard lock(m_tileEntityListCS); - for (unsigned int i = 0; i < tileEntityList.size();) { - bool removed = false; - std::shared_ptr te = tileEntityList[i]; - if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && - te->y < y1 && te->z < z1) { - LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); - if (lc != nullptr) { - // Only remove tile entities where this is no longer a tile - // entity - int tileId = lc->getTile(te->x & 15, te->y, te->z & 15); - if (Tile::tiles[tileId] == nullptr || - !Tile::tiles[tileId]->isEntityTile()) { - tileEntityList[i] = tileEntityList.back(); - tileEntityList.pop_back(); + for (unsigned int i = 0; i < tileEntityList.size();) { + bool removed = false; + std::shared_ptr te = tileEntityList[i]; + if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && + te->y < y1 && te->z < z1) { + LevelChunk* lc = getChunk(te->x >> 4, te->z >> 4); + if (lc != nullptr) { + // Only remove tile entities where this is no longer a tile + // entity + int tileId = lc->getTile(te->x & 15, te->y, te->z & 15); + if (Tile::tiles[tileId] == nullptr || + !Tile::tiles[tileId]->isEntityTile()) { + tileEntityList[i] = tileEntityList.back(); + tileEntityList.pop_back(); - // 4J Stu - Chests can create new tile entities when being - // removed, so disable this - m_bDisableAddNewTileEntities = true; - lc->removeTileEntity(te->x & 15, te->y, te->z & 15); - m_bDisableAddNewTileEntities = false; - removed = true; + // 4J Stu - Chests can create new tile entities when being + // removed, so disable this + m_bDisableAddNewTileEntities = true; + lc->removeTileEntity(te->x & 15, te->y, te->z & 15); + m_bDisableAddNewTileEntities = false; + removed = true; + } } } + if (!removed) i++; } - if (!removed) i++; } - - LeaveCriticalSection(&m_tileEntityListCS); } diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index 3fae07502..6108d2405 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "../Platform/stdafx.h" #include "ServerLevel.h" @@ -45,7 +46,7 @@ WeighedTreasureArray ServerLevel::RANDOM_BONUS_ITEMS; C4JThread* ServerLevel::m_updateThread = nullptr; C4JThread::EventArray* ServerLevel::m_updateTrigger; -CRITICAL_SECTION ServerLevel::m_updateCS[3]; +std::mutex ServerLevel::m_updateCS[3]; Level* ServerLevel::m_level[3]; int ServerLevel::m_updateChunkX[3][LEVEL_CHUNKS_TO_UPDATE_MAX]; @@ -59,9 +60,6 @@ int ServerLevel::m_randValue[3]; void ServerLevel::staticCtor() { m_updateTrigger = new C4JThread::EventArray(3); - InitializeCriticalSection(&m_updateCS[0]); - InitializeCriticalSection(&m_updateCS[1]); - InitializeCriticalSection(&m_updateCS[2]); m_updateThread = new C4JThread(runUpdate, nullptr, "Tile update"); m_updateThread->SetProcessor(CPU_CORE_TILE_UPDATE); @@ -107,9 +105,6 @@ ServerLevel::ServerLevel(MinecraftServer* server, LevelSettings* levelSettings) : Level(levelStorage, levelName, levelSettings, Dimension::getNew(dimension), false) { - InitializeCriticalSection(&m_limiterCS); - InitializeCriticalSection(&m_tickNextTickCS); - InitializeCriticalSection(&m_csQueueSendTileUpdates); m_fallingTileCount = 0; m_primedTntCount = 0; @@ -188,30 +183,24 @@ ServerLevel::~ServerLevel() { delete portalForcer; delete mobSpawner; - EnterCriticalSection(&m_csQueueSendTileUpdates); - for (auto it = m_queuedSendTileUpdates.begin(); - it != m_queuedSendTileUpdates.end(); ++it) { - Pos* p = *it; - delete p; + { + std::lock_guard lock(m_csQueueSendTileUpdates); + for (auto it = m_queuedSendTileUpdates.begin(); + it != m_queuedSendTileUpdates.end(); ++it) { + Pos* p = *it; + delete p; + } + m_queuedSendTileUpdates.clear(); + + delete this->tracker; // MGH - added, we were losing about 500K going in + // and out the menus + delete this->chunkMap; } - m_queuedSendTileUpdates.clear(); - - delete this->tracker; // MGH - added, we were losing about 500K going in - // and out the menus - delete this->chunkMap; - - LeaveCriticalSection(&m_csQueueSendTileUpdates); - DeleteCriticalSection(&m_csQueueSendTileUpdates); - DeleteCriticalSection(&m_limiterCS); - DeleteCriticalSection(&m_tickNextTickCS); // Make sure that the update thread isn't actually doing any updating - EnterCriticalSection(&m_updateCS[0]); - LeaveCriticalSection(&m_updateCS[0]); - EnterCriticalSection(&m_updateCS[1]); - LeaveCriticalSection(&m_updateCS[1]); - EnterCriticalSection(&m_updateCS[2]); - LeaveCriticalSection(&m_updateCS[2]); + { std::lock_guard lock(m_updateCS[0]); } + { std::lock_guard lock(m_updateCS[1]); } + { std::lock_guard lock(m_updateCS[2]); } m_updateTrigger->ClearAll(); } @@ -450,31 +439,32 @@ void ServerLevel::tickTiles() { unsigned int tickCount = 0; - EnterCriticalSection(&m_updateCS[iLev]); - // This section processes the tiles that need to be ticked, which we worked - // out in the previous tick (or haven't yet, if this is the first frame) - /*int grassTicks = 0; - int lavaTicks = 0; - int otherTicks = 0;*/ - for (int i = 0; i < m_updateTileCount[iLev]; i++) { - int x = m_updateTileX[iLev][i]; - int y = m_updateTileY[iLev][i]; - int z = m_updateTileZ[iLev][i]; - if (hasChunkAt(x, y, z)) { - int id = getTile(x, y, z); - if (Tile::tiles[id] != nullptr && Tile::tiles[id]->isTicking()) { - /*if(id == 2) ++grassTicks; - else if(id == 11) ++lavaTicks; - else ++otherTicks;*/ - Tile::tiles[id]->tick(this, x, y, z, random); + { + std::lock_guard lock(m_updateCS[iLev]); + // This section processes the tiles that need to be ticked, which we worked + // out in the previous tick (or haven't yet, if this is the first frame) + /*int grassTicks = 0; + int lavaTicks = 0; + int otherTicks = 0;*/ + for (int i = 0; i < m_updateTileCount[iLev]; i++) { + int x = m_updateTileX[iLev][i]; + int y = m_updateTileY[iLev][i]; + int z = m_updateTileZ[iLev][i]; + if (hasChunkAt(x, y, z)) { + int id = getTile(x, y, z); + if (Tile::tiles[id] != nullptr && Tile::tiles[id]->isTicking()) { + /*if(id == 2) ++grassTicks; + else if(id == 11) ++lavaTicks; + else ++otherTicks;*/ + Tile::tiles[id]->tick(this, x, y, z, random); + } } } + // printf("Total ticks - Grass: %d, Lava: %d, Other: %d, Total: %d\n", + // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + otherTicks); + m_updateTileCount[iLev] = 0; + m_updateChunkCount[iLev] = 0; } - // printf("Total ticks - Grass: %d, Lava: %d, Other: %d, Total: %d\n", - // grassTicks, lavaTicks, otherTicks, grassTicks + lavaTicks + otherTicks); - m_updateTileCount[iLev] = 0; - m_updateChunkCount[iLev] = 0; - LeaveCriticalSection(&m_updateCS[iLev]); Level::tickTiles(); @@ -603,12 +593,13 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, td.delay(tickDelay + levelData->getGameTime()); td.setPriorityTilt(priorityTilt); } - EnterCriticalSection(&m_tickNextTickCS); - if (tickNextTickSet.find(td) == tickNextTickSet.end()) { - tickNextTickSet.insert(td); - tickNextTickList.insert(td); + { + std::lock_guard lock(m_tickNextTickCS); + if (tickNextTickSet.find(td) == tickNextTickSet.end()) { + tickNextTickSet.insert(td); + tickNextTickList.insert(td); + } } - LeaveCriticalSection(&m_tickNextTickCS); } MemSect(0); } @@ -621,12 +612,13 @@ void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId, if (tileId > 0) { td.delay(tickDelay + levelData->getGameTime()); } - EnterCriticalSection(&m_tickNextTickCS); - if (tickNextTickSet.find(td) == tickNextTickSet.end()) { - tickNextTickSet.insert(td); - tickNextTickList.insert(td); + { + std::lock_guard lock(m_tickNextTickCS); + if (tickNextTickSet.find(td) == tickNextTickSet.end()) { + tickNextTickSet.insert(td); + tickNextTickList.insert(td); + } } - LeaveCriticalSection(&m_tickNextTickCS); } void ServerLevel::tickEntities() { @@ -644,7 +636,7 @@ void ServerLevel::tickEntities() { void ServerLevel::resetEmptyTime() { emptyTime = 0; } bool ServerLevel::tickPendingTicks(bool force) { - EnterCriticalSection(&m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); int count = (int)tickNextTickList.size(); int count2 = (int)tickNextTickSet.size(); if (count != tickNextTickSet.size()) { @@ -687,14 +679,13 @@ bool ServerLevel::tickPendingTicks(bool force) { int count4 = (int)tickNextTickSet.size(); bool retval = tickNextTickList.size() != 0; - LeaveCriticalSection(&m_tickNextTickCS); return retval; } std::vector* ServerLevel::fetchTicksInChunk(LevelChunk* chunk, bool remove) { - EnterCriticalSection(&m_tickNextTickCS); + std::lock_guard lock(m_tickNextTickCS); std::vector* results = new std::vector; ChunkPos* pos = chunk->getPos(); @@ -749,7 +740,6 @@ std::vector* ServerLevel::fetchTicksInChunk(LevelChunk* chunk, } } - LeaveCriticalSection(&m_tickNextTickCS); return results; } @@ -1225,13 +1215,12 @@ void ServerLevel::sendParticles(const std::wstring& name, double x, double y, // 4J Stu - Sometimes we want to update tiles on the server from the main thread // (eg SignTileEntity when string verify returns) void ServerLevel::queueSendTileUpdate(int x, int y, int z) { - EnterCriticalSection(&m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); m_queuedSendTileUpdates.push_back(new Pos(x, y, z)); - LeaveCriticalSection(&m_csQueueSendTileUpdates); } void ServerLevel::runQueuedSendTileUpdates() { - EnterCriticalSection(&m_csQueueSendTileUpdates); + std::lock_guard lock(m_csQueueSendTileUpdates); for (auto it = m_queuedSendTileUpdates.begin(); it != m_queuedSendTileUpdates.end(); ++it) { Pos* p = *it; @@ -1239,7 +1228,6 @@ void ServerLevel::runQueuedSendTileUpdates() { delete p; } m_queuedSendTileUpdates.clear(); - LeaveCriticalSection(&m_csQueueSendTileUpdates); } // 4J - added special versions of addEntity and extra processing on entity @@ -1249,53 +1237,48 @@ bool ServerLevel::addEntity(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_itemEntities.size() >= MAX_ITEM_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_itemEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an hanging entity, and we've got to our capacity, delete the // oldest else if (e->instanceof(eTYPE_HANGING_ENTITY)) { // printf("Adding item entity count //%d\n",m_itemEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_hangingEntities.size() >= MAX_HANGING_ENTITIES) { // printf("Adding - doing remove\n"); // 4J-PB - refuse to add the entity, since we'll be removing one // already there, and it may be an item frame with something in it. - LeaveCriticalSection(&m_limiterCS); return false; // removeEntityImmediately(m_hangingEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an arrow entity, and we've got to our capacity, delete the oldest else if (e->instanceof(eTYPE_ARROW)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_arrowEntities.size() >= MAX_ARROW_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_arrowEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } // If its an experience orb entity, and we've got to our capacity, delete // the oldest else if (e->instanceof(eTYPE_EXPERIENCEORB)) { // printf("Adding arrow entity count //%d\n",m_arrowEntities.size()); - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); if (m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES) { // printf("Adding - doing remove\n"); removeEntityImmediately(m_experienceOrbEntities.front()); } - LeaveCriticalSection(&m_limiterCS); } return Level::addEntity(e); } @@ -1308,21 +1291,17 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { bool atLimit = false; if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_itemEntities.size() >= MAX_ITEM_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_hangingEntities.size() >= MAX_HANGING_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_arrowEntities.size() >= MAX_ARROW_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); atLimit = m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES; - LeaveCriticalSection(&m_limiterCS); } return atLimit; @@ -1331,37 +1310,31 @@ bool ServerLevel::atEntityLimit(std::shared_ptr e) { // Maintain a cound of primed tnt & falling tiles in this level void ServerLevel::entityAddedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_itemEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_hangingEntities.push_back(e); // printf("entity added: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_arrowEntities.push_back(e); // printf("entity added: arrow entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_experienceOrbEntities.push_back(e); // printf("entity added: experience orb entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount++; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_FALLINGTILE)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount++; - LeaveCriticalSection(&m_limiterCS); } } @@ -1369,7 +1342,7 @@ void ServerLevel::entityAddedExtra(std::shared_ptr e) { // item entities from our list void ServerLevel::entityRemovedExtra(std::shared_ptr e) { if (e->instanceof(eTYPE_ITEMENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = find(m_itemEntities.begin(), m_itemEntities.end(), e); @@ -1379,9 +1352,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_HANGING_ENTITY)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: item entity count //%d\n",m_itemEntities.size()); auto it = @@ -1392,9 +1364,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: item entity count now //%d\n",m_itemEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_ARROW)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: arrow entity count //%d\n",m_arrowEntities.size()); auto it = find(m_arrowEntities.begin(), m_arrowEntities.end(), e); @@ -1404,9 +1375,8 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: arrow entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); // printf("entity removed: experience orb entity count //%d\n",m_arrowEntities.size()); auto it = find(m_experienceOrbEntities.begin(), @@ -1417,29 +1387,24 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr e) { } // printf("entity removed: experience orb entity count now //%d\n",m_arrowEntities.size()); - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_primedTntCount--; - LeaveCriticalSection(&m_limiterCS); } else if (e->instanceof(eTYPE_FALLINGTILE)) { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); m_fallingTileCount--; - LeaveCriticalSection(&m_limiterCS); } } bool ServerLevel::newPrimedTntAllowed() { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_primedTntCount < MAX_PRIMED_TNT; - LeaveCriticalSection(&m_limiterCS); return retval; } bool ServerLevel::newFallingTileAllowed() { - EnterCriticalSection(&m_limiterCS); + std::lock_guard lock(m_limiterCS); bool retval = m_fallingTileCount < MAX_FALLING_TILE; - LeaveCriticalSection(&m_limiterCS); return retval; } @@ -1458,7 +1423,7 @@ int ServerLevel::runUpdate(void* lpParam) { int grassTicks = 0; int lavaTicks = 0; for (unsigned int iLev = 0; iLev < 3; ++iLev) { - EnterCriticalSection(&m_updateCS[iLev]); + std::lock_guard lock(m_updateCS[iLev]); for (int i = 0; i < m_updateChunkCount[iLev]; i++) { // 4J - some of these tile ticks will check things in // neighbouring tiles, causing chunks to load/create that aren't @@ -1548,7 +1513,6 @@ int ServerLevel::runUpdate(void* lpParam) { } } } - LeaveCriticalSection(&m_updateCS[iLev]); } PIXEndNamedEvent(); } diff --git a/Minecraft.Client/Level/ServerLevel.h b/Minecraft.Client/Level/ServerLevel.h index a704d6ed7..74b5e87dd 100644 --- a/Minecraft.Client/Level/ServerLevel.h +++ b/Minecraft.Client/Level/ServerLevel.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/Util/JavaIntHash.h" class ServerChunkCache; @@ -16,7 +17,7 @@ private: EntityTracker* tracker; PlayerChunkMap* chunkMap; - CRITICAL_SECTION m_tickNextTickCS; // 4J added + std::mutex m_tickNextTickCS; // 4J added std::set tickNextTickList; // 4J Was TreeSet std::unordered_set m_queuedSendTileUpdates; // 4J added - CRITICAL_SECTION m_csQueueSendTileUpdates; + std::mutex m_csQueueSendTileUpdates; protected: int saveInterval; @@ -177,7 +178,7 @@ public: int m_primedTntCount; int m_fallingTileCount; - CRITICAL_SECTION m_limiterCS; + std::mutex m_limiterCS; std::list > m_itemEntities; std::list > m_hangingEntities; std::list > m_arrowEntities; @@ -211,7 +212,7 @@ public: static int m_randValue[3]; static C4JThread::EventArray* m_updateTrigger; - static CRITICAL_SECTION m_updateCS[3]; + static std::mutex m_updateCS[3]; static C4JThread* m_updateThread; static int runUpdate(void* lpParam); diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 1d97f3e47..65075ecee 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -121,8 +121,6 @@ Minecraft::Minecraft(Component* mouseComponent, Canvas* parent, rightClickDelay = 0; // 4J Stu Added - InitializeCriticalSection(&ProgressRenderer::s_progress); - InitializeCriticalSection(&m_setLevelCS); // m_hPlayerRespawned = CreateEvent(nullptr, false, false, nullptr); progressRenderer = nullptr; @@ -987,7 +985,7 @@ void Minecraft::run_middle() { } #endif - EnterCriticalSection(&m_setLevelCS); + { std::lock_guard lock(m_setLevelCS); if (running) { if (reloadTextures) { @@ -1734,7 +1732,7 @@ void Minecraft::run_middle() { } */ } - LeaveCriticalSection(&m_setLevelCS); + } // lock_guard scope } void Minecraft::run_end() { destroy(); } @@ -3670,7 +3668,7 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/, std::shared_ptr forceInsertPlayer /*=nullptr*/, bool doForceStatsSave /*=true*/, bool bPrimaryPlayerSignedOut /*=false*/) { - EnterCriticalSection(&m_setLevelCS); + std::lock_guard lock(m_setLevelCS); bool playerAdded = false; this->cameraTargetPlayer = nullptr; @@ -3842,7 +3840,6 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/, // System.gc(); // 4J - removed // 4J removed // this->lastTickTime = 0; - LeaveCriticalSection(&m_setLevelCS); } void Minecraft::prepareLevel(int title) { diff --git a/Minecraft.Client/Minecraft.h b/Minecraft.Client/Minecraft.h index b496e1c5b..7b738e7bb 100644 --- a/Minecraft.Client/Minecraft.h +++ b/Minecraft.Client/Minecraft.h @@ -1,4 +1,5 @@ #pragma once +#include class Timer; class MultiPlayerLevel; class LevelRenderer; @@ -347,7 +348,7 @@ public: // 4J Stu void forceStatsSave(int idx); - CRITICAL_SECTION m_setLevelCS; + std::mutex m_setLevelCS; private: // A bit field that store whether a particular quadrant is in the full diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 39f47ac36..59d72e68f 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -243,38 +243,39 @@ int MinecraftServer::runPostUpdate(void* lpParam) { // Update lights for both levels until we are signalled to terminate do { - EnterCriticalSection(&server->m_postProcessCS); - if (server->m_postProcessRequests.size()) { - MinecraftServer::postProcessRequest request = - server->m_postProcessRequests.back(); - server->m_postProcessRequests.pop_back(); - LeaveCriticalSection(&server->m_postProcessCS); - static int count = 0; - PIXBeginNamedEvent(0, "Post processing %d ", (count++) % 8); - request.chunkSource->postProcess(request.chunkSource, request.x, - request.z); - PIXEndNamedEvent(); - } else { - LeaveCriticalSection(&server->m_postProcessCS); + { + std::unique_lock lock(server->m_postProcessCS); + if (server->m_postProcessRequests.size()) { + MinecraftServer::postProcessRequest request = + server->m_postProcessRequests.back(); + server->m_postProcessRequests.pop_back(); + lock.unlock(); + static int count = 0; + PIXBeginNamedEvent(0, "Post processing %d ", (count++) % 8); + request.chunkSource->postProcess(request.chunkSource, request.x, + request.z); + PIXEndNamedEvent(); + } } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (!server->m_postUpdateTerminate && ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)); // #ifndef 0 // One final pass through updates to make sure we're done - EnterCriticalSection(&server->m_postProcessCS); - int maxRequests = server->m_postProcessRequests.size(); - while (server->m_postProcessRequests.size() && - ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { - MinecraftServer::postProcessRequest request = - server->m_postProcessRequests.back(); - server->m_postProcessRequests.pop_back(); - LeaveCriticalSection(&server->m_postProcessCS); - request.chunkSource->postProcess(request.chunkSource, request.x, - request.z); - EnterCriticalSection(&server->m_postProcessCS); + { + std::unique_lock lock(server->m_postProcessCS); + int maxRequests = server->m_postProcessRequests.size(); + while (server->m_postProcessRequests.size() && + ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread)) { + MinecraftServer::postProcessRequest request = + server->m_postProcessRequests.back(); + server->m_postProcessRequests.pop_back(); + lock.unlock(); + request.chunkSource->postProcess(request.chunkSource, request.x, + request.z); + lock.lock(); + } } - LeaveCriticalSection(&server->m_postProcessCS); // #endif //0 Tile::ReleaseThreadStorage(); Level::destroyLightingCache(); @@ -286,26 +287,28 @@ int MinecraftServer::runPostUpdate(void* lpParam) { void MinecraftServer::addPostProcessRequest(ChunkSource* chunkSource, int x, int z) { - EnterCriticalSection(&m_postProcessCS); + { std::lock_guard lock(m_postProcessCS); m_postProcessRequests.push_back( MinecraftServer::postProcessRequest(x, z, chunkSource)); - LeaveCriticalSection(&m_postProcessCS); + } } void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { std::uint32_t status = 0; + size_t postProcessItemCount = 0; + size_t postProcessItemRemaining = 0; - EnterCriticalSection(&server->m_postProcessCS); - size_t postProcessItemCount = server->m_postProcessRequests.size(); - LeaveCriticalSection(&server->m_postProcessCS); + { std::lock_guard lock(server->m_postProcessCS); + postProcessItemCount = server->m_postProcessRequests.size(); + } do { status = m_postUpdateThread->WaitForCompletion(50); if (status == WAIT_TIMEOUT) { - EnterCriticalSection(&server->m_postProcessCS); - size_t postProcessItemRemaining = + { std::lock_guard lock(server->m_postProcessCS); + postProcessItemRemaining = server->m_postProcessRequests.size(); - LeaveCriticalSection(&server->m_postProcessCS); + } if (postProcessItemCount) { mcprogress->progressStagePercentage( @@ -319,7 +322,6 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { } while (status == WAIT_TIMEOUT); delete m_postUpdateThread; m_postUpdateThread = nullptr; - DeleteCriticalSection(&m_postProcessCS); } bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, @@ -481,7 +483,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, if (s_bServerHalted || !g_NetworkManager.IsInSession()) return false; // 4J - Make a new thread to do post processing - InitializeCriticalSection(&m_postProcessCS); // 4J-PB - fix for 108310 - TCR #001 BAS Game Stability: TU12: Code: // Compliance: Crash after creating world on "journey" seed. Stack gets very diff --git a/Minecraft.Client/MinecraftServer.h b/Minecraft.Client/MinecraftServer.h index 737f49fd2..8a91dd724 100644 --- a/Minecraft.Client/MinecraftServer.h +++ b/Minecraft.Client/MinecraftServer.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "Input/ConsoleInputSource.h" #include "../Minecraft.World/Util/ArrayWithLength.h" @@ -247,7 +248,7 @@ private: : x(x), z(z), chunkSource(chunkSource) {} }; std::vector m_postProcessRequests; - CRITICAL_SECTION m_postProcessCS; + std::mutex m_postProcessCS; public: void addPostProcessRequest(ChunkSource* chunkSource, int x, int z); diff --git a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp index c8537b5aa..be1a0cae8 100644 --- a/Minecraft.Client/Network/MultiPlayerChunkCache.cpp +++ b/Minecraft.Client/Network/MultiPlayerChunkCache.cpp @@ -89,7 +89,6 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level* level) { this->cache = new LevelChunk*[XZSIZE * XZSIZE]; memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk*)); - InitializeCriticalSectionAndSpinCount(&m_csLoadCreate, 4000); } MultiPlayerChunkCache::~MultiPlayerChunkCache() { @@ -100,8 +99,6 @@ MultiPlayerChunkCache::~MultiPlayerChunkCache() { auto itEnd = loadedChunkList.end(); for (auto it = loadedChunkList.begin(); it != itEnd; it++) delete *it; - - DeleteCriticalSection(&m_csLoadCreate); } bool MultiPlayerChunkCache::hasChunk(int x, int z) { @@ -158,7 +155,7 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { LevelChunk* lastChunk = chunk; if (chunk == nullptr) { - EnterCriticalSection(&m_csLoadCreate); + { std::unique_lock lock(m_csLoadCreate); // LevelChunk *chunk; if (g_NetworkManager.IsHost()) // force here to disable sharing of data @@ -199,8 +196,7 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { } chunk->loaded = true; - - LeaveCriticalSection(&m_csLoadCreate); + } #if (defined _WIN64 || defined __LP64__) if (InterlockedCompareExchangeRelease64( @@ -220,9 +216,9 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) { } // Successfully updated the cache - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); loadedChunkList.push_back(chunk); - LeaveCriticalSection(&m_csLoadCreate); + } } else { // Something else must have updated the cache. Return that chunk and // discard this one. This really shouldn't be happening in @@ -281,9 +277,10 @@ void MultiPlayerChunkCache::recreateLogicStructuresForChunk(int chunkX, int chunkZ) {} std::wstring MultiPlayerChunkCache::gatherStats() { - EnterCriticalSection(&m_csLoadCreate); - int size = (int)loadedChunkList.size(); - LeaveCriticalSection(&m_csLoadCreate); + int size; + { std::lock_guard lock(m_csLoadCreate); + size = (int)loadedChunkList.size(); + } return L"MultiplayerChunkCache: " + _toString(size); } diff --git a/Minecraft.Client/Network/MultiPlayerChunkCache.h b/Minecraft.Client/Network/MultiPlayerChunkCache.h index ef14a168f..63b114bf9 100644 --- a/Minecraft.Client/Network/MultiPlayerChunkCache.h +++ b/Minecraft.Client/Network/MultiPlayerChunkCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.h" #include "../../Minecraft.World/Level/RandomLevelSource.h" @@ -18,7 +19,7 @@ private: LevelChunk** cache; // 4J - added for multithreaded support - CRITICAL_SECTION m_csLoadCreate; + std::mutex m_csLoadCreate; // 4J - size of cache is defined by size of one side - must be even int XZSIZE; int XZOFFSET; diff --git a/Minecraft.Client/Network/PlayerConnection.cpp b/Minecraft.Client/Network/PlayerConnection.cpp index f4f1cab17..f517299be 100644 --- a/Minecraft.Client/Network/PlayerConnection.cpp +++ b/Minecraft.Client/Network/PlayerConnection.cpp @@ -57,8 +57,6 @@ PlayerConnection::PlayerConnection(MinecraftServer* server, this->player = player; // player->connection = this; // 4J - moved out as we can't // assign in a ctor - InitializeCriticalSection(&done_cs); - m_bCloseOnTick = false; m_bWasKicked = false; @@ -73,7 +71,6 @@ PlayerConnection::PlayerConnection(MinecraftServer* server, PlayerConnection::~PlayerConnection() { delete connection; - DeleteCriticalSection(&done_cs); } void PlayerConnection::tick() { @@ -106,9 +103,8 @@ void PlayerConnection::tick() { } void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason) { - EnterCriticalSection(&done_cs); + std::lock_guard lock(done_cs); if (done) { - LeaveCriticalSection(&done_cs); return; } @@ -135,7 +131,6 @@ void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason) { server->getPlayers()->remove(player); done = true; - LeaveCriticalSection(&done_cs); } void PlayerConnection::handlePlayerInput( @@ -555,7 +550,7 @@ void PlayerConnection::handleUseItem(std::shared_ptr packet) { void PlayerConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, void* reasonObjects) { - EnterCriticalSection(&done_cs); + std::lock_guard lock(done_cs); if (done) return; // logger.info(player.name + " lost connection: " + reason); // 4J-PB - removed, since it needs to be localised in the language the @@ -572,7 +567,6 @@ void PlayerConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, } server->getPlayers()->remove(player); done = true; - LeaveCriticalSection(&done_cs); } void PlayerConnection::onUnhandledPacket(std::shared_ptr packet) { diff --git a/Minecraft.Client/Network/PlayerConnection.h b/Minecraft.Client/Network/PlayerConnection.h index cdc5f4e9f..b3956acba 100644 --- a/Minecraft.Client/Network/PlayerConnection.h +++ b/Minecraft.Client/Network/PlayerConnection.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Input/ConsoleInputSource.h" #include "../../Minecraft.World/Network/Packets/PacketListener.h" #include "../../Minecraft.World/Util/JavaIntHash.h" @@ -14,7 +15,7 @@ class PlayerConnection : public PacketListener, public ConsoleInputSource { public: Connection* connection; bool done; - CRITICAL_SECTION done_cs; + std::mutex done_cs; // 4J Stu - Added this so that we can manage UGC privileges PlayerUID m_offlineXUID, m_onlineXUID; diff --git a/Minecraft.Client/Network/PlayerList.cpp b/Minecraft.Client/Network/PlayerList.cpp index 9d9eda446..efdf6e2fb 100644 --- a/Minecraft.Client/Network/PlayerList.cpp +++ b/Minecraft.Client/Network/PlayerList.cpp @@ -49,8 +49,6 @@ PlayerList::PlayerList(MinecraftServer* server) { maxPlayers = server->settings->getInt(L"max-players", 20); doWhiteList = false; - InitializeCriticalSection(&m_kickPlayersCS); - InitializeCriticalSection(&m_closePlayersCS); } PlayerList::~PlayerList() { @@ -62,8 +60,6 @@ PlayerList::~PlayerList() { (*it)->gameMode = nullptr; } - DeleteCriticalSection(&m_kickPlayersCS); - DeleteCriticalSection(&m_closePlayersCS); } void PlayerList::placeNewPlayer(Connection* connection, @@ -997,7 +993,7 @@ void PlayerList::tick() { } } - EnterCriticalSection(&m_closePlayersCS); + { std::lock_guard lock(m_closePlayersCS); while (!m_smallIdsToClose.empty()) { std::uint8_t smallId = m_smallIdsToClose.front(); m_smallIdsToClose.pop_front(); @@ -1023,9 +1019,9 @@ void PlayerList::tick() { DisconnectPacket::eDisconnect_Closed); } } - LeaveCriticalSection(&m_closePlayersCS); + } - EnterCriticalSection(&m_kickPlayersCS); + { std::lock_guard lock(m_kickPlayersCS); while (!m_smallIdsToKick.empty()) { std::uint8_t smallId = m_smallIdsToKick.front(); m_smallIdsToKick.pop_front(); @@ -1063,7 +1059,7 @@ void PlayerList::tick() { } } } - LeaveCriticalSection(&m_kickPlayersCS); + } // Check our receiving players, and if they are dead see if we can replace // them @@ -1628,15 +1624,15 @@ bool PlayerList::canReceiveAllPackets(std::shared_ptr player) { } void PlayerList::kickPlayerByShortId(std::uint8_t networkSmallId) { - EnterCriticalSection(&m_kickPlayersCS); + { std::lock_guard lock(m_kickPlayersCS); m_smallIdsToKick.push_back(networkSmallId); - LeaveCriticalSection(&m_kickPlayersCS); + } } void PlayerList::closePlayerConnectionBySmallId(std::uint8_t networkSmallId) { - EnterCriticalSection(&m_closePlayersCS); + { std::lock_guard lock(m_closePlayersCS); m_smallIdsToClose.push_back(networkSmallId); - LeaveCriticalSection(&m_closePlayersCS); + } } bool PlayerList::isXuidBanned(PlayerUID xuid) { diff --git a/Minecraft.Client/Network/PlayerList.h b/Minecraft.Client/Network/PlayerList.h index b430128a9..77371f3cb 100644 --- a/Minecraft.Client/Network/PlayerList.h +++ b/Minecraft.Client/Network/PlayerList.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "../../Minecraft.World/Util/ArrayWithLength.h" class ServerPlayer; @@ -31,9 +32,9 @@ private: // 4J Added std::vector m_bannedXuids; std::deque m_smallIdsToKick; - CRITICAL_SECTION m_kickPlayersCS; + std::mutex m_kickPlayersCS; std::deque m_smallIdsToClose; - CRITICAL_SECTION m_closePlayersCS; + std::mutex m_closePlayersCS; /* 4J - removed Set bans = new HashSet(); Set ipBans = new HashSet(); diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 685133744..148857e6c 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -39,7 +39,6 @@ ServerChunkCache::ServerChunkCache(ServerLevel* level, ChunkStorage* storage, memset(m_unloadedCache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk*)); #endif - InitializeCriticalSectionAndSpinCount(&m_csLoadCreate, 4000); } // 4J-PB added @@ -58,7 +57,6 @@ ServerChunkCache::~ServerChunkCache() { auto itEnd = m_loadedChunkList.end(); for (auto it = m_loadedChunkList.begin(); it != itEnd; it++) delete *it; - DeleteCriticalSection(&m_csLoadCreate); } bool ServerChunkCache::hasChunk(int x, int z) { @@ -146,7 +144,7 @@ LevelChunk* ServerChunkCache::create( LevelChunk* lastChunk = chunk; if ((chunk == nullptr) || (chunk->x != x) || (chunk->z != z)) { - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); chunk = load(x, z); if (chunk == nullptr) { if (source == nullptr) { @@ -158,8 +156,7 @@ LevelChunk* ServerChunkCache::create( if (chunk != nullptr) { chunk->load(); } - - LeaveCriticalSection(&m_csLoadCreate); + } #if defined(_WIN64) || defined(__LP64__) if (InterlockedCompareExchangeRelease64( @@ -172,7 +169,7 @@ LevelChunk* ServerChunkCache::create( #endif { // Successfully updated the cache - EnterCriticalSection(&m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); // 4J - added - this will run a recalcHeightmap if source is a // randomlevelsource, which has been split out from source::getChunk // so that we are doing it after the chunk has been added to the @@ -269,7 +266,6 @@ LevelChunk* ServerChunkCache::create( hasChunk(x, z - 1) && hasChunk(x, z + 1)) chunk->checkChests(this, x, z); - LeaveCriticalSection(&m_csLoadCreate); } else { // Something else must have updated the cache. Return that chunk and // discard this one @@ -653,12 +649,12 @@ bool ServerChunkCache::saveAllEntities() { PIXBeginNamedEvent(0, "Save all entities"); PIXBeginNamedEvent(0, "saving to NBT"); - EnterCriticalSection(&m_csLoadCreate); + { std::lock_guard lock(m_csLoadCreate); for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end(); ++it) { storage->saveEntities(level, *it); } - LeaveCriticalSection(&m_csLoadCreate); + } PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Flushing"); @@ -670,7 +666,7 @@ bool ServerChunkCache::saveAllEntities() { } bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { - EnterCriticalSection(&m_csLoadCreate); + std::lock_guard lock(m_csLoadCreate); int saves = 0; // 4J - added this to support progressListner @@ -701,7 +697,6 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { save(chunk); chunk->setUnsaved(false); if (++saves == MAX_SAVES && !force) { - LeaveCriticalSection(&m_csLoadCreate); return false; } @@ -751,7 +746,6 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { save(chunk); chunk->setUnsaved(false); if (++saves == MAX_SAVES && !force) { - LeaveCriticalSection(&m_csLoadCreate); return false; } @@ -776,13 +770,11 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) { if (force) { if (storage == nullptr) { - LeaveCriticalSection(&m_csLoadCreate); return true; } storage->flush(); } - LeaveCriticalSection(&m_csLoadCreate); return !maxSavesReached; } diff --git a/Minecraft.Client/Network/ServerChunkCache.h b/Minecraft.Client/Network/ServerChunkCache.h index abd7cb4b7..d39049ac6 100644 --- a/Minecraft.Client/Network/ServerChunkCache.h +++ b/Minecraft.Client/Network/ServerChunkCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../Minecraft.World/Headers/net.minecraft.world.level.h" #include "../../Minecraft.World/IO/Files/File.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h" @@ -30,7 +31,7 @@ private: #endif // 4J - added for multithreaded support - CRITICAL_SECTION m_csLoadCreate; + std::mutex m_csLoadCreate; // 4J - size of cache is defined by size of one side - must be even int XZSIZE; int XZOFFSET; diff --git a/Minecraft.Client/Network/ServerConnection.cpp b/Minecraft.Client/Network/ServerConnection.cpp index 04285c507..270722a07 100644 --- a/Minecraft.Client/Network/ServerConnection.cpp +++ b/Minecraft.Client/Network/ServerConnection.cpp @@ -12,12 +12,11 @@ ServerConnection::ServerConnection(MinecraftServer* server) { // 4J - added initialiser connectionCounter = 0; - InitializeCriticalSection(&pending_cs); this->server = server; } -ServerConnection::~ServerConnection() { DeleteCriticalSection(&pending_cs); } +ServerConnection::~ServerConnection() {} // 4J - added to handle incoming connections, to replace thread that original // used to have @@ -35,18 +34,18 @@ void ServerConnection::addPlayerConnection( } void ServerConnection::handleConnection(std::shared_ptr uc) { - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); pending.push_back(uc); - LeaveCriticalSection(&pending_cs); + } } void ServerConnection::stop() { - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); for (unsigned int i = 0; i < pending.size(); i++) { std::shared_ptr uc = pending[i]; uc->connection->close(DisconnectPacket::eDisconnect_Closed); } - LeaveCriticalSection(&pending_cs); + } for (unsigned int i = 0; i < players.size(); i++) { std::shared_ptr player = players[i]; @@ -58,9 +57,10 @@ void ServerConnection::tick() { { // MGH - changed this so that the the CS lock doesn't cover the tick // (was causing a lockup when 2 players tried to join) - EnterCriticalSection(&pending_cs); - std::vector > tempPending = pending; - LeaveCriticalSection(&pending_cs); + std::vector > tempPending; + { std::lock_guard lock(pending_cs); + tempPending = pending; + } for (unsigned int i = 0; i < tempPending.size(); i++) { std::shared_ptr uc = tempPending[i]; @@ -76,13 +76,13 @@ void ServerConnection::tick() { } // now remove from the pending list - EnterCriticalSection(&pending_cs); + { std::lock_guard lock(pending_cs); for (unsigned int i = 0; i < pending.size(); i++) if (pending[i]->done) { pending.erase(pending.begin() + i); i--; } - LeaveCriticalSection(&pending_cs); + } for (unsigned int i = 0; i < players.size(); i++) { std::shared_ptr player = players[i]; diff --git a/Minecraft.Client/Network/ServerConnection.h b/Minecraft.Client/Network/ServerConnection.h index 68ab89448..c5dd92998 100644 --- a/Minecraft.Client/Network/ServerConnection.h +++ b/Minecraft.Client/Network/ServerConnection.h @@ -1,4 +1,5 @@ #pragma once +#include class PendingConnection; class PlayerConnection; class MinecraftServer; @@ -18,7 +19,7 @@ private: int connectionCounter; private: - CRITICAL_SECTION pending_cs; // 4J added + std::mutex pending_cs; // 4J added std::vector > pending; std::vector > players; diff --git a/Minecraft.Client/Platform/Common/C4JMemoryPool.h b/Minecraft.Client/Platform/Common/C4JMemoryPool.h index 9e9b4db95..2a9e08522 100644 --- a/Minecraft.Client/Platform/Common/C4JMemoryPool.h +++ b/Minecraft.Client/Platform/Common/C4JMemoryPool.h @@ -28,7 +28,6 @@ class C4JMemoryPoolFixed : public C4JMemoryPool uchar* m_memStart; // Beginning of memory pool uchar* m_memEnd; // End of memory pool uchar* m_next; // Num of next free block -// CRITICAL_SECTION m_CS; public: C4JMemoryPoolFixed() { @@ -59,7 +58,6 @@ public: m_numOfBlocks ]; m_memEnd = m_memStart + (m_sizeOfEachBlock * m_numOfBlocks); m_next = m_memStart; -// InitializeCriticalSection(&m_CS); } void DestroyPool() @@ -82,7 +80,6 @@ public: { if(size > m_sizeOfEachBlock) return ::malloc(size); -// EnterCriticalSection(&m_CS); if (m_numInitialized < m_numOfBlocks ) { uint* p = (uint*)AddrFromIndex( m_numInitialized ); @@ -103,7 +100,6 @@ public: m_next = nullptr; } } -// LeaveCriticalSection(&m_CS); return ret; } @@ -114,7 +110,6 @@ public: ::free(ptr); return; } -// EnterCriticalSection(&m_CS); if (m_next != nullptr) { (*(uint*)ptr) = IndexFromAddr( m_next ); @@ -126,7 +121,6 @@ public: m_next = (uchar*)ptr; } ++m_numFreeBlocks; -// LeaveCriticalSection(&m_CS); } }; // End pool class diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp index 1c9fbfbbc..b8e05780a 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.cpp +++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp @@ -178,17 +178,8 @@ CMinecraftApp::CMinecraftApp() { m_iDLCOfferC = 0; m_bAllDLCContentRetrieved = true; - InitializeCriticalSection(&csDLCDownloadQueue); m_bAllTMSContentRetrieved = true; m_bTickTMSDLCFiles = true; - InitializeCriticalSection(&csTMSPPDownloadQueue); - InitializeCriticalSection(&csAdditionalModelParts); - InitializeCriticalSection(&csAdditionalSkinBoxes); - InitializeCriticalSection(&csAnimOverrideBitmask); - InitializeCriticalSection(&csMemFilesLock); - InitializeCriticalSection(&csMemTPDLock); - - InitializeCriticalSection(&m_saveNotificationCriticalSection); m_saveNotificationDepth = 0; m_dwRequiredTexturePackID = 0; @@ -4579,7 +4570,7 @@ bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid) { void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, std::uint8_t* pbData, unsigned int byteCount) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_Files.find(wName); @@ -4599,7 +4590,6 @@ void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, } ++pData->ucRefCount; - LeaveCriticalSection(&csMemFilesLock); return; } @@ -4618,12 +4608,10 @@ void CMinecraftApp::AddMemoryTextureFile(const std::wstring& wName, // use the xuid to access the skin data m_MEM_Files[wName] = pData; - - LeaveCriticalSection(&csMemFilesLock); } void CMinecraftApp::RemoveMemoryTextureFile(const std::wstring& wName) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { @@ -4642,17 +4630,16 @@ void CMinecraftApp::RemoveMemoryTextureFile(const std::wstring& wName) { m_MEM_Files.erase(wName); } } - LeaveCriticalSection(&csMemFilesLock); } bool CMinecraftApp::DefaultCapeExists() { std::wstring wTex = L"Special_Cape.png"; bool val = false; - EnterCriticalSection(&csMemFilesLock); + { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wTex); if (it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); + } return val; } @@ -4660,10 +4647,10 @@ bool CMinecraftApp::DefaultCapeExists() { bool CMinecraftApp::IsFileInMemoryTextures(const std::wstring& wName) { bool val = false; - EnterCriticalSection(&csMemFilesLock); + { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) val = true; - LeaveCriticalSection(&csMemFilesLock); + } return val; } @@ -4671,19 +4658,18 @@ bool CMinecraftApp::IsFileInMemoryTextures(const std::wstring& wName) { void CMinecraftApp::GetMemFileDetails(const std::wstring& wName, std::uint8_t** ppbData, unsigned int* pByteCount) { - EnterCriticalSection(&csMemFilesLock); + std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { PMEMDATA pData = (*it).second; *ppbData = pData->pbData; *pByteCount = pData->byteCount; } - LeaveCriticalSection(&csMemFilesLock); } void CMinecraftApp::AddMemoryTPDFile(int iConfig, std::uint8_t* pbData, unsigned int byteCount) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_TPD.find(iConfig); @@ -4695,12 +4681,10 @@ void CMinecraftApp::AddMemoryTPDFile(int iConfig, std::uint8_t* pbData, m_MEM_TPD[iConfig] = pData; } - - LeaveCriticalSection(&csMemTPDLock); } void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); // check it's not already in PMEMDATA pData = nullptr; auto it = m_MEM_TPD.find(iConfig); @@ -4709,8 +4693,6 @@ void CMinecraftApp::RemoveMemoryTPDFile(int iConfig) { delete pData; m_MEM_TPD.erase(iConfig); } - - LeaveCriticalSection(&csMemTPDLock); } #if defined(_WINDOWS64) @@ -4719,24 +4701,23 @@ int CMinecraftApp::GetTPConfigVal(wchar_t* pwchDataFile) { return -1; } bool CMinecraftApp::IsFileInTPD(int iConfig) { bool val = false; - EnterCriticalSection(&csMemTPDLock); + { std::lock_guard lock(csMemTPDLock); auto it = m_MEM_TPD.find(iConfig); if (it != m_MEM_TPD.end()) val = true; - LeaveCriticalSection(&csMemTPDLock); + } return val; } void CMinecraftApp::GetTPD(int iConfig, std::uint8_t** ppbData, unsigned int* pByteCount) { - EnterCriticalSection(&csMemTPDLock); + std::lock_guard lock(csMemTPDLock); auto it = m_MEM_TPD.find(iConfig); if (it != m_MEM_TPD.end()) { PMEMDATA pData = (*it).second; *ppbData = pData->pbData; *pByteCount = pData->byteCount; } - LeaveCriticalSection(&csMemTPDLock); } // bool CMinecraftApp::UploadFileToGlobalStorage(int iQuadrant, @@ -5691,7 +5672,7 @@ DLC_INFO* CMinecraftApp::GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { } void CMinecraftApp::EnterSaveNotificationSection() { - EnterCriticalSection(&m_saveNotificationCriticalSection); + std::lock_guard lock(m_saveNotificationCriticalSection); if (m_saveNotificationDepth++ == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if @@ -5707,11 +5688,10 @@ void CMinecraftApp::EnterSaveNotificationSection() { } } } - LeaveCriticalSection(&m_saveNotificationCriticalSection); } void CMinecraftApp::LeaveSaveNotificationSection() { - EnterCriticalSection(&m_saveNotificationCriticalSection); + std::lock_guard lock(m_saveNotificationCriticalSection); if (--m_saveNotificationDepth == 0) { if (g_NetworkManager .IsInSession()) // this can be triggered from the front end if @@ -5727,7 +5707,6 @@ void CMinecraftApp::LeaveSaveNotificationSection() { } } } - LeaveCriticalSection(&m_saveNotificationCriticalSection); } int CMinecraftApp::RemoteSaveThreadProc(void* lpParameter) { @@ -6662,7 +6641,7 @@ std::uint32_t CMinecraftApp::m_dwContentTypeA[e_Marketplace_MAX] = { unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, bool bPromote) { // lock access - EnterCriticalSection(&csDLCDownloadQueue); + { std::lock_guard lock(csDLCDownloadQueue); // If it's already in there, promote it to the top of the list int iPosition = 0; @@ -6675,7 +6654,6 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, if (pCurrent->eState == e_DLC_ContentState_Retrieving || pCurrent->eState == e_DLC_ContentState_Retrieved) { // already retrieved this - LeaveCriticalSection(&csDLCDownloadQueue); return 0; } else { // promote @@ -6685,7 +6663,6 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), pCurrent); } - LeaveCriticalSection(&csDLCDownloadQueue); return 0; } } @@ -6699,7 +6676,7 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, m_DLCDownloadQueue.push_back(pDLCreq); m_bAllDLCContentRetrieved = false; - LeaveCriticalSection(&csDLCDownloadQueue); + } app.DebugPrintf("[Consoles_App] Added DLC request.\n"); return 1; @@ -6708,7 +6685,7 @@ unsigned int CMinecraftApp::AddDLCRequest(eDLCMarketplaceType eType, unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, bool bPromote) { // lock access - EnterCriticalSection(&csTMSPPDownloadQueue); + std::lock_guard lock(csTMSPPDownloadQueue); // If it's already in there, promote it to the top of the list int iPosition = 0; @@ -6742,7 +6719,6 @@ unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, if(bPromoted) { // re-ordered the list, so leave now - LeaveCriticalSection(&csTMSPPDownloadQueue); return 0; } */ @@ -6889,22 +6865,19 @@ unsigned int CMinecraftApp::AddTMSPPFileTypeRequest(eDLCContentType eType, } } - LeaveCriticalSection(&csTMSPPDownloadQueue); return 1; } bool CMinecraftApp::CheckTMSDLCCanStop() { - EnterCriticalSection(&csTMSPPDownloadQueue); + std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_TMSPPDownloadQueue.begin(); it != m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; if (pCurrent->eState == e_TMS_ContentState_Retrieving) { - LeaveCriticalSection(&csTMSPPDownloadQueue); return false; } } - LeaveCriticalSection(&csTMSPPDownloadQueue); return true; } @@ -6920,13 +6893,12 @@ bool CMinecraftApp::RetrieveNextDLCContent() { // online. } - EnterCriticalSection(&csDLCDownloadQueue); + { std::lock_guard lock(csDLCDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; if (pCurrent->eState == e_DLC_ContentState_Retrieving) { - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } @@ -6952,11 +6924,10 @@ bool CMinecraftApp::RetrieveNextDLCContent() { app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); pCurrent->eState = e_DLC_ContentState_Retrieved; } - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } - LeaveCriticalSection(&csDLCDownloadQueue); + } app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); return false; @@ -6969,7 +6940,7 @@ int CMinecraftApp::TMSPPFileReturned(void* pParam, int iPad, int iUserData, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + { std::lock_guard lock(pClass->csTMSPPDownloadQueue); for (auto it = pClass->m_TMSPPDownloadQueue.begin(); it != pClass->m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; @@ -7008,7 +6979,7 @@ int CMinecraftApp::TMSPPFileReturned(void* pParam, int iPad, int iUserData, break; } } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + } return 0; } @@ -7029,7 +7000,7 @@ void CMinecraftApp::ClearAndResetDLCDownloadQueue() { app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); int iPosition = 0; - EnterCriticalSection(&csTMSPPDownloadQueue); + { std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; @@ -7039,7 +7010,7 @@ void CMinecraftApp::ClearAndResetDLCDownloadQueue() { } m_DLCDownloadQueue.clear(); m_bAllDLCContentRetrieved = true; - LeaveCriticalSection(&csTMSPPDownloadQueue); + } } void CMinecraftApp::TickTMSPPFilesRetrieved() { @@ -7051,7 +7022,7 @@ void CMinecraftApp::TickTMSPPFilesRetrieved() { } void CMinecraftApp::ClearTMSPPFilesRetrieved() { int iPosition = 0; - EnterCriticalSection(&csTMSPPDownloadQueue); + { std::lock_guard lock(csTMSPPDownloadQueue); for (auto it = m_TMSPPDownloadQueue.begin(); it != m_TMSPPDownloadQueue.end(); ++it) { TMSPPRequest* pCurrent = *it; @@ -7061,7 +7032,7 @@ void CMinecraftApp::ClearTMSPPFilesRetrieved() { } m_TMSPPDownloadQueue.clear(); m_bAllTMSContentRetrieved = true; - LeaveCriticalSection(&csTMSPPDownloadQueue); + } } int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, @@ -7069,7 +7040,7 @@ int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, CMinecraftApp* pClass = (CMinecraftApp*)pParam; // find the right one in the vector - EnterCriticalSection(&pClass->csTMSPPDownloadQueue); + { std::lock_guard lock(pClass->csTMSPPDownloadQueue); for (auto it = pClass->m_DLCDownloadQueue.begin(); it != pClass->m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; @@ -7086,7 +7057,7 @@ int CMinecraftApp::DLCOffersReturned(void* pParam, int iOfferC, break; } } - LeaveCriticalSection(&pClass->csTMSPPDownloadQueue); + } return 0; } @@ -7101,18 +7072,16 @@ eDLCContentType CMinecraftApp::Find_eDLCContentType(std::uint32_t dwType) { bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType) { // If there's already a retrieve in progress, quit // we may have re-ordered the list, so need to check every item - EnterCriticalSection(&csDLCDownloadQueue); + std::lock_guard lock(csDLCDownloadQueue); for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); ++it) { DLCRequest* pCurrent = *it; if ((pCurrent->dwType == m_dwContentTypeA[eType]) && (pCurrent->eState == e_DLC_ContentState_Retrieved)) { - LeaveCriticalSection(&csDLCDownloadQueue); return true; } } - LeaveCriticalSection(&csDLCDownloadQueue); return false; } @@ -7125,8 +7094,8 @@ void CMinecraftApp::SetAdditionalSkinBoxes(std::uint32_t dwSkinID, std::vector* pvModelPart = new std::vector; std::vector* pvSkinBoxes = new std::vector; - EnterCriticalSection(&csAdditionalModelParts); - EnterCriticalSection(&csAdditionalSkinBoxes); + { std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " @@ -7148,9 +7117,7 @@ void CMinecraftApp::SetAdditionalSkinBoxes(std::uint32_t dwSkinID, m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxes)); - - LeaveCriticalSection(&csAdditionalSkinBoxes); - LeaveCriticalSection(&csAdditionalModelParts); + } } std::vector* CMinecraftApp::SetAdditionalSkinBoxes( @@ -7160,8 +7127,8 @@ std::vector* CMinecraftApp::SetAdditionalSkinBoxes( Model* pModel = renderer->getModel(); std::vector* pvModelPart = new std::vector; - EnterCriticalSection(&csAdditionalModelParts); - EnterCriticalSection(&csAdditionalSkinBoxes); + { std::lock_guard lock_mp(csAdditionalModelParts); + std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d from " "array of Skin Boxes\n", @@ -7181,15 +7148,13 @@ std::vector* CMinecraftApp::SetAdditionalSkinBoxes( m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxA)); - - LeaveCriticalSection(&csAdditionalSkinBoxes); - LeaveCriticalSection(&csAdditionalModelParts); + } return pvModelPart; } std::vector* CMinecraftApp::GetAdditionalModelParts( std::uint32_t dwSkinID) { - EnterCriticalSection(&csAdditionalModelParts); + std::lock_guard lock(csAdditionalModelParts); std::vector* pvModelParts = nullptr; if (m_AdditionalModelParts.size() > 0) { auto it = m_AdditionalModelParts.find(dwSkinID); @@ -7198,13 +7163,12 @@ std::vector* CMinecraftApp::GetAdditionalModelParts( } } - LeaveCriticalSection(&csAdditionalModelParts); return pvModelParts; } std::vector* CMinecraftApp::GetAdditionalSkinBoxes( std::uint32_t dwSkinID) { - EnterCriticalSection(&csAdditionalSkinBoxes); + std::lock_guard lock(csAdditionalSkinBoxes); std::vector* pvSkinBoxes = nullptr; if (m_AdditionalSkinBoxes.size() > 0) { auto it = m_AdditionalSkinBoxes.find(dwSkinID); @@ -7213,12 +7177,11 @@ std::vector* CMinecraftApp::GetAdditionalSkinBoxes( } } - LeaveCriticalSection(&csAdditionalSkinBoxes); return pvSkinBoxes; } unsigned int CMinecraftApp::GetAnimOverrideBitmask(std::uint32_t dwSkinID) { - EnterCriticalSection(&csAnimOverrideBitmask); + std::lock_guard lock(csAnimOverrideBitmask); unsigned int uiAnimOverrideBitmask = 0L; if (m_AnimOverrides.size() > 0) { @@ -7228,25 +7191,22 @@ unsigned int CMinecraftApp::GetAnimOverrideBitmask(std::uint32_t dwSkinID) { } } - LeaveCriticalSection(&csAnimOverrideBitmask); return uiAnimOverrideBitmask; } void CMinecraftApp::SetAnimOverrideBitmask(std::uint32_t dwSkinID, unsigned int uiAnimOverrideBitmask) { // Make thread safe - EnterCriticalSection(&csAnimOverrideBitmask); + std::lock_guard lock(csAnimOverrideBitmask); if (m_AnimOverrides.size() > 0) { auto it = m_AnimOverrides.find(dwSkinID); if (it != m_AnimOverrides.end()) { - LeaveCriticalSection(&csAnimOverrideBitmask); return; // already in here } } m_AnimOverrides.insert(std::pair( dwSkinID, uiAnimOverrideBitmask)); - LeaveCriticalSection(&csAnimOverrideBitmask); } std::uint32_t CMinecraftApp::getSkinIdFromPath(const std::wstring& skin) { diff --git a/Minecraft.Client/Platform/Common/Consoles_App.h b/Minecraft.Client/Platform/Common/Consoles_App.h index b293dc8d5..41d289d65 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.h +++ b/Minecraft.Client/Platform/Common/Consoles_App.h @@ -1,6 +1,7 @@ #pragma once #include +#include // using namespace std; @@ -462,8 +463,8 @@ private: std::unordered_map m_MEM_Files; // for storing texture pack data files std::unordered_map m_MEM_TPD; - CRITICAL_SECTION csMemFilesLock; // For locking access to the above map - CRITICAL_SECTION csMemTPDLock; // For locking access to the above map + std::mutex csMemFilesLock; // For locking access to the above map + std::mutex csMemTPDLock; // For locking access to the above map VNOTIFICATIONS m_vNotifications; @@ -885,7 +886,7 @@ public: void LeaveSaveNotificationSection(); private: - CRITICAL_SECTION m_saveNotificationCriticalSection; + std::mutex m_saveNotificationCriticalSection; int m_saveNotificationDepth; // Download Status @@ -897,11 +898,11 @@ private: bool m_bAllDLCContentRetrieved; bool m_bAllTMSContentRetrieved; bool m_bTickTMSDLCFiles; - CRITICAL_SECTION csDLCDownloadQueue; - CRITICAL_SECTION csTMSPPDownloadQueue; - CRITICAL_SECTION csAdditionalModelParts; - CRITICAL_SECTION csAdditionalSkinBoxes; - CRITICAL_SECTION csAnimOverrideBitmask; + std::mutex csDLCDownloadQueue; + std::mutex csTMSPPDownloadQueue; + std::mutex csAdditionalModelParts; + std::mutex csAdditionalSkinBoxes; + std::mutex csAnimOverrideBitmask; bool m_bCorruptSaveDeleted; std::uint32_t m_dwAdditionalModelParts[XUSER_MAX_COUNT]; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp index b0415e64e..ec14637b4 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp @@ -33,7 +33,6 @@ SonyLeaderboardManager::SonyLeaderboardManager() { m_openSessions = 0; - InitializeCriticalSection(&m_csViewsLock); m_running = false; m_threadScoreboard = nullptr; @@ -51,7 +50,6 @@ SonyLeaderboardManager::~SonyLeaderboardManager() { delete m_threadScoreboard; - DeleteCriticalSection(&m_csViewsLock); } int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { @@ -68,9 +66,9 @@ int SonyLeaderboardManager::scoreboardThreadEntry(void* lpParam) { self->scoreboardThreadInternal(); } - EnterCriticalSection(&self->m_csViewsLock); + { std::lock_guard lock(self->m_csViewsLock); needsWriting = self->m_views.size() > 0; - LeaveCriticalSection(&self->m_csViewsLock); + } // 4J Stu - We can't write while we aren't signed in to live if (!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) { @@ -166,9 +164,10 @@ void SonyLeaderboardManager::scoreboardThreadInternal() { // 4J-JEV: Writing no longer changes the manager state, // we'll manage the write queue seperately. - EnterCriticalSection(&m_csViewsLock); - bool hasWork = !m_views.empty(); - LeaveCriticalSection(&m_csViewsLock); + bool hasWork; + { std::lock_guard lock(m_csViewsLock); + hasWork = !m_views.empty(); + } if (hasWork) { setScore(); @@ -495,10 +494,11 @@ bool SonyLeaderboardManager::setScore() { // Get next job. - EnterCriticalSection(&m_csViewsLock); - RegisterScore rscore = m_views.front(); + RegisterScore rscore; + { std::lock_guard lock(m_csViewsLock); + rscore = m_views.front(); m_views.pop(); - LeaveCriticalSection(&m_csViewsLock); + } if (ProfileManager.IsGuest(rscore.m_iPad)) { app.DebugPrintf( @@ -521,9 +521,8 @@ bool SonyLeaderboardManager::setScore() { // Start emptying queue if leaderboards has been closed. if (ret == SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED) { - EnterCriticalSection(&m_csViewsLock); + std::lock_guard lock(m_csViewsLock); m_views.pop(); - LeaveCriticalSection(&m_csViewsLock); } // Error handling. @@ -685,7 +684,7 @@ bool SonyLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) { // Write relevant parameters. // RegisterScore *regScore = reinterpret_cast(views); - EnterCriticalSection(&m_csViewsLock); + { std::lock_guard lock(m_csViewsLock); for (int i = 0; i < viewCount; i++) { app.DebugPrintf( "[SonyLeaderboardManager] WriteStats(), starting. difficulty=%i, " @@ -695,7 +694,7 @@ bool SonyLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) { m_views.push(views[i]); } - LeaveCriticalSection(&m_csViewsLock); + } delete[] views; //*regScore; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h index f7946c510..258ab60c4 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Common/Leaderboards/LeaderboardManager.h" @@ -40,7 +41,7 @@ protected: std::queue m_views; - CRITICAL_SECTION m_csViewsLock; + std::mutex m_csViewsLock; EStatsState m_eStatsState; // State of the stats read // EFilterMode m_eFilterMode; diff --git a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp index 4c1bbfca7..e54781483 100644 --- a/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp @@ -5,6 +5,7 @@ #include "../../Minecraft.Client/Level/MultiPlayerLevel.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.dimension.h" #include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h" +#include UIComponent_Panorama::UIComponent_Panorama(int iPad, void* initData, UILayer* parentLayer) @@ -42,25 +43,26 @@ void UIComponent_Panorama::tick() { if (!hasMovie()) return; Minecraft* pMinecraft = Minecraft::GetInstance(); - EnterCriticalSection(&pMinecraft->m_setLevelCS); - if (pMinecraft->level != nullptr) { - int64_t i64TimeOfDay = 0; - // are we in the Nether? - Leave the time as 0 if we are, so we show - // daylight - if (pMinecraft->level->dimension->id == 0) { - i64TimeOfDay = - pMinecraft->level->getLevelData()->getGameTime() % 24000; - } + { + std::lock_guard lock(pMinecraft->m_setLevelCS); + if (pMinecraft->level != nullptr) { + int64_t i64TimeOfDay = 0; + // are we in the Nether? - Leave the time as 0 if we are, so we show + // daylight + if (pMinecraft->level->dimension->id == 0) { + i64TimeOfDay = + pMinecraft->level->getLevelData()->getGameTime() % 24000; + } - if (i64TimeOfDay > 14000) { - setPanorama(false); + if (i64TimeOfDay > 14000) { + setPanorama(false); + } else { + setPanorama(true); + } } else { setPanorama(true); } - } else { - setPanorama(true); } - LeaveCriticalSection(&pMinecraft->m_setLevelCS); UIScene::tick(); } diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index 5e77f549d..ff8747a5c 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -34,7 +34,7 @@ #endif -CRITICAL_SECTION UIController::ms_reloadSkinCS; +std::mutex UIController::ms_reloadSkinCS; bool UIController::ms_bReloadSkinCSInitialised = false; std::uint32_t UIController::m_dwTrialTimerLimitSecs = @@ -125,7 +125,7 @@ static void* RADLINK AllocateFunction(void* alloc_callback_user_data, size_t size_requested, size_t* size_returned) { UIController* controller = (UIController*)alloc_callback_user_data; - EnterCriticalSection(&controller->m_Allocatorlock); + std::lock_guard lock(controller->m_Allocatorlock); #if defined(EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR) void* alloc = __real_malloc(size_requested); #else @@ -136,14 +136,13 @@ static void* RADLINK AllocateFunction(void* alloc_callback_user_data, allocations[alloc] = size_requested; app.DebugPrintf(app.USER_SR, "Allocating %d, new total: %d\n", size_requested, UIController::iggyAllocCount); - LeaveCriticalSection(&controller->m_Allocatorlock); return alloc; } static void RADLINK DeallocateFunction(void* alloc_callback_user_data, void* ptr) { UIController* controller = (UIController*)alloc_callback_user_data; - EnterCriticalSection(&controller->m_Allocatorlock); + std::lock_guard lock(controller->m_Allocatorlock); size_t size = allocations[ptr]; UIController::iggyAllocCount -= size; allocations.erase(ptr); @@ -154,7 +153,6 @@ static void RADLINK DeallocateFunction(void* alloc_callback_user_data, #else free(ptr); #endif - LeaveCriticalSection(&controller->m_Allocatorlock); } UIController::UIController() { @@ -173,7 +171,7 @@ UIController::UIController() { m_eCurrentFont = m_eTargetFont = eFont_NotLoaded; #if defined(ENABLE_IGGY_ALLOCATOR) - InitializeCriticalSection(&m_Allocatorlock); + // std::mutex is default-constructed, no initialization needed #endif // 4J Stu - This is a bit of a hack until we change the Minecraft @@ -214,15 +212,12 @@ UIController::UIController() { m_accumulatedTicks = 0; m_lastUiSfx = 0; - InitializeCriticalSection(&m_navigationLock); - InitializeCriticalSection(&m_registeredCallbackScenesCS); // m_bSysUIShowing=false; m_bSystemUIShowing = false; if (!ms_bReloadSkinCSInitialised) { // MGH - added to prevent crash loading Iggy movies while the skins were // being reloaded - InitializeCriticalSection(&ms_reloadSkinCS); ms_bReloadSkinCSInitialised = true; } } @@ -620,27 +615,27 @@ void UIController::StartReloadSkinThread() { } int UIController::reloadSkinThreadProc(void* lpParam) { - EnterCriticalSection( - &ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies - // while the skins were being reloaded - UIController* controller = (UIController*)lpParam; - // Load new skin - controller->loadSkins(); + { + std::lock_guard lock(ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies + // while the skins were being reloaded + UIController* controller = (UIController*)lpParam; + // Load new skin + controller->loadSkins(); - // Reload all scene swf - for (int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) { - controller->m_groups[i]->ReloadAll(); - } + // Reload all scene swf + for (int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) { + controller->m_groups[i]->ReloadAll(); + } - // Always reload the fullscreen group - controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); + // Always reload the fullscreen group + controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); - // 4J Stu - Don't do this on windows, as we never navigated forwards to - // start with + // 4J Stu - Don't do this on windows, as we never navigated forwards to + // start with #if !(defined(_WINDOWS64) || defined(__linux__)) - controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); + controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); #endif - LeaveCriticalSection(&ms_reloadSkinCS); + } return 0; } @@ -1256,13 +1251,15 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void* initData, PerformanceTimer timer; - EnterCriticalSection(&m_navigationLock); - SetMenuDisplayed(menuDisplayedPad, true); - bool success = - m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); - if (success && group == eUIGroup_Fullscreen) - setFullscreenMenuDisplayed(true); - LeaveCriticalSection(&m_navigationLock); + bool success; + { + std::lock_guard lock(m_navigationLock); + SetMenuDisplayed(menuDisplayedPad, true); + success = + m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); + if (success && group == eUIGroup_Fullscreen) + setFullscreenMenuDisplayed(true); + } timer.PrintElapsedTime(L"Navigate to scene"); @@ -1380,24 +1377,22 @@ UIScene* UIController::GetTopScene(int iPad, EUILayer layer, EUIGroup group) { } size_t UIController::RegisterForCallbackId(UIScene* scene) { - EnterCriticalSection(&m_registeredCallbackScenesCS); + std::lock_guard lock(m_registeredCallbackScenesCS); size_t newId = GetTickCount(); newId &= 0xFFFFFF; // Chop off the top byte, we don't need any more // accuracy than that newId |= (scene->getSceneType() << 24); // Add in the scene's type to help keep this unique m_registeredCallbackScenes[newId] = scene; - LeaveCriticalSection(&m_registeredCallbackScenesCS); return newId; } void UIController::UnregisterCallbackId(size_t id) { - EnterCriticalSection(&m_registeredCallbackScenesCS); + std::lock_guard lock(m_registeredCallbackScenesCS); auto it = m_registeredCallbackScenes.find(id); if (it != m_registeredCallbackScenes.end()) { m_registeredCallbackScenes.erase(it); } - LeaveCriticalSection(&m_registeredCallbackScenesCS); } UIScene* UIController::GetSceneFromCallbackId(size_t id) { @@ -1410,11 +1405,11 @@ UIScene* UIController::GetSceneFromCallbackId(size_t id) { } void UIController::EnterCallbackIdCriticalSection() { - EnterCriticalSection(&m_registeredCallbackScenesCS); + m_registeredCallbackScenesCS.lock(); } void UIController::LeaveCallbackIdCriticalSection() { - LeaveCriticalSection(&m_registeredCallbackScenesCS); + m_registeredCallbackScenesCS.unlock(); } void UIController::CloseAllPlayersScenes() { diff --git a/Minecraft.Client/Platform/Common/UI/UIController.h b/Minecraft.Client/Platform/Common/UI/UIController.h index 3eb04a6d4..c934e42cf 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.h +++ b/Minecraft.Client/Platform/Common/UI/UIController.h @@ -1,6 +1,7 @@ #pragma once // using namespace std; #include +#include #include "IUIController.h" #include "UIEnums.h" @@ -20,7 +21,7 @@ public: // MGH - added to prevent crash loading Iggy movies while the skins were // being reloaded - static CRITICAL_SECTION ms_reloadSkinCS; + static std::mutex ms_reloadSkinCS; static bool ms_bReloadSkinCSInitialised; protected: @@ -28,7 +29,7 @@ protected: UIComponent_DebugUIMarketingGuide* m_uiDebugMarketingGuide; private: - CRITICAL_SECTION m_navigationLock; + std::mutex m_navigationLock; static const int UI_REPEAT_KEY_DELAY_MS = 300; // How long from press until the first repeat @@ -165,7 +166,7 @@ private: // that are used in async callbacks so we // can safely handle when they get // destroyed - CRITICAL_SECTION m_registeredCallbackScenesCS; + std::mutex m_registeredCallbackScenesCS; ; public: @@ -190,7 +191,7 @@ protected: void postInit(); public: - CRITICAL_SECTION m_Allocatorlock; + std::mutex m_Allocatorlock; void SetupFont(); bool PendingFontChange(); bool UsingBitmapFont(); diff --git a/Minecraft.Client/Platform/Common/UI/UIScene.cpp b/Minecraft.Client/Platform/Common/UI/UIScene.cpp index f033acdb8..4c99ef35f 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene.cpp @@ -1,4 +1,5 @@ #include "../../Minecraft.World/Platform/stdafx.h" +#include #include "UI.h" #include "UIScene.h" @@ -245,12 +246,11 @@ bool UIScene::mapElementsAndNames() { return true; } -extern CRITICAL_SECTION s_loadSkinCS; +extern std::mutex s_loadSkinCS; void UIScene::loadMovie() { - EnterCriticalSection( - &UIController::ms_reloadSkinCS); // MGH - added to prevent crash - // loading Iggy movies while the skins - // were being reloaded + UIController::ms_reloadSkinCS.lock(); // MGH - added to prevent crash + // loading Iggy movies while the skins + // were being reloaded std::wstring moviePath = getMoviePath(); #if defined(_WINDOWS64) @@ -320,7 +320,7 @@ void UIScene::loadMovie() { IggyPlayerSetUserdata(swf, this); // #ifdef _DEBUG - LeaveCriticalSection(&UIController::ms_reloadSkinCS); + UIController::ms_reloadSkinCS.unlock(); } void UIScene::getDebugMemoryUseRecursive(const std::wstring& moviePath, diff --git a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp index 608c6b1b7..fce89e4d9 100644 --- a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp +++ b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp @@ -4,6 +4,7 @@ #include "../../../Minecraft.World/Platform/stdafx.h" #include +#include // #include #if defined(__linux__) && defined(__GLIBC__) #include @@ -1046,7 +1047,7 @@ bool trackStarted = false; volatile size_t sizeCheckMin = 1160; volatile size_t sizeCheckMax = 1160; volatile int sectCheck = 48; -CRITICAL_SECTION memCS; +std::mutex memCS; uint32_t tlsIdx; void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { @@ -1057,33 +1058,34 @@ void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { return p; } - EnterCriticalSection(&memCS); + void* p; + { + std::lock_guard lock(memCS); - void* p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); - size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; + p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); + size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; - *(((unsigned char*)p) + realSize) = sect; + if (trackEnable) { + int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; + *(((unsigned char*)p) + realSize) = sect; - if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && - ((sect == sectCheck) || (sectCheck == -1))) { - app.DebugPrintf("Found one\n"); - } + if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && + ((sect == sectCheck) || (sectCheck == -1))) { + app.DebugPrintf("Found one\n"); + } - if (p) { - totalAllocGen += realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount + 1; + if (p) { + totalAllocGen += realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount + 1; - trackEnable = true; + trackEnable = true; + } } } - LeaveCriticalSection(&memCS); - return p; } @@ -1114,22 +1116,23 @@ void WINAPI XMemFree(void* pAddress, uint32_t dwAllocAttributes) { totalAllocGen -= realSize; return; } - EnterCriticalSection(&memCS); - if (pAddress) { - size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; + { + std::lock_guard lock(memCS); + if (pAddress) { + size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = *(((unsigned char*)pAddress) + realSize); - totalAllocGen -= realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount - 1; - trackEnable = true; + if (trackEnable) { + int sect = *(((unsigned char*)pAddress) + realSize); + totalAllocGen -= realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount - 1; + trackEnable = true; + } + XMemFreeDefault(pAddress, dwAllocAttributes); } - XMemFreeDefault(pAddress, dwAllocAttributes); } - LeaveCriticalSection(&memCS); } size_t WINAPI XMemSize(void* pAddress, uint32_t dwAllocAttributes) { @@ -1158,14 +1161,14 @@ void ResetMem() { trackEnable = true; trackStarted = true; totalAllocGen = 0; - InitializeCriticalSection(&memCS); tlsIdx = TlsAlloc(); } - EnterCriticalSection(&memCS); - trackEnable = false; - allocCounts.clear(); - trackEnable = true; - LeaveCriticalSection(&memCS); + { + std::lock_guard lock(memCS); + trackEnable = false; + allocCounts.clear(); + trackEnable = true; + } } void MemSect(int section) { diff --git a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h index 1cd6dc5c8..91530b893 100644 --- a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h +++ b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h @@ -249,46 +249,6 @@ typedef HINSTANCE HMODULE; #define E_ABORT _HRESULT_TYPEDEF_(0x80004004L) #define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L) -typedef pthread_mutex_t RTL_CRITICAL_SECTION; -typedef pthread_mutex_t* PRTL_CRITICAL_SECTION; - -typedef RTL_CRITICAL_SECTION CRITICAL_SECTION; -typedef PRTL_CRITICAL_SECTION PCRITICAL_SECTION; -typedef PRTL_CRITICAL_SECTION LPCRITICAL_SECTION; - -static inline void InitializeCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(CriticalSection, &attr); - pthread_mutexattr_destroy(&attr); -} - -static inline void InitializeCriticalSectionAndSpinCount( - PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount) { - // no spin count required because we use a recursive mutex - InitializeCriticalSection(CriticalSection); -} - -static inline void DeleteCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_destroy(CriticalSection); -} - -static inline void EnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_lock(CriticalSection); -} - -static inline void LeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) { - pthread_mutex_unlock(CriticalSection); -} - -static inline ULONG TryEnterCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) { - return pthread_mutex_trylock(CriticalSection) == 0; -} - // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalmemorystatus static inline void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) { // TODO: Parse /proc/meminfo and set lpBuffer based on that. Probably will diff --git a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp index 1c90eca18..b3ff25707 100644 --- a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp @@ -4,6 +4,7 @@ #include "../../../Minecraft.World/Platform/stdafx.h" #include +#include #include "GameConfig/Minecraft.spa.h" #include "../../MinecraftServer.h" #include "../../Player/LocalPlayer.h" @@ -932,7 +933,7 @@ bool trackStarted = false; volatile size_t sizeCheckMin = 1160; volatile size_t sizeCheckMax = 1160; volatile int sectCheck = 48; -CRITICAL_SECTION memCS; +std::mutex memCS; uint32_t tlsIdx; void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { @@ -943,33 +944,34 @@ void* XMemAlloc(size_t dwSize, uint32_t dwAllocAttributes) { return p; } - EnterCriticalSection(&memCS); + void* p; + { + std::lock_guard lock(memCS); - void* p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); - size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; + p = XMemAllocDefault(dwSize + 16, dwAllocAttributes); + size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; - *(((unsigned char*)p) + realSize) = sect; + if (trackEnable) { + int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f; + *(((unsigned char*)p) + realSize) = sect; - if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && - ((sect == sectCheck) || (sectCheck == -1))) { - app.DebugPrintf("Found one\n"); - } + if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && + ((sect == sectCheck) || (sectCheck == -1))) { + app.DebugPrintf("Found one\n"); + } - if (p) { - totalAllocGen += realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount + 1; + if (p) { + totalAllocGen += realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount + 1; - trackEnable = true; + trackEnable = true; + } } } - LeaveCriticalSection(&memCS); - return p; } @@ -1000,22 +1002,23 @@ void WINAPI XMemFree(void* pAddress, uint32_t dwAllocAttributes) { totalAllocGen -= realSize; return; } - EnterCriticalSection(&memCS); - if (pAddress) { - size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; + { + std::lock_guard lock(memCS); + if (pAddress) { + size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16; - if (trackEnable) { - int sect = *(((unsigned char*)pAddress) + realSize); - totalAllocGen -= realSize; - trackEnable = false; - int key = (sect << 26) | realSize; - int oldCount = allocCounts[key]; - allocCounts[key] = oldCount - 1; - trackEnable = true; + if (trackEnable) { + int sect = *(((unsigned char*)pAddress) + realSize); + totalAllocGen -= realSize; + trackEnable = false; + int key = (sect << 26) | realSize; + int oldCount = allocCounts[key]; + allocCounts[key] = oldCount - 1; + trackEnable = true; + } + XMemFreeDefault(pAddress, dwAllocAttributes); } - XMemFreeDefault(pAddress, dwAllocAttributes); } - LeaveCriticalSection(&memCS); } size_t WINAPI XMemSize(void* pAddress, uint32_t dwAllocAttributes) { @@ -1044,14 +1047,14 @@ void ResetMem() { trackEnable = true; trackStarted = true; totalAllocGen = 0; - InitializeCriticalSection(&memCS); tlsIdx = TlsAlloc(); } - EnterCriticalSection(&memCS); - trackEnable = false; - allocCounts.clear(); - trackEnable = true; - LeaveCriticalSection(&memCS); + { + std::lock_guard lock(memCS); + trackEnable = false; + allocCounts.clear(); + trackEnable = true; + } } void MemSect(int section) { diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp index 1743b524b..419454d62 100644 --- a/Minecraft.Client/Rendering/Chunk.cpp +++ b/Minecraft.Client/Rendering/Chunk.cpp @@ -9,6 +9,7 @@ #include "LevelRenderer.h" #include "../Utils/FrameProfiler.h" #include +#include int Chunk::updates = 0; @@ -92,7 +93,7 @@ void Chunk::reconcileRenderableTileEntities( // TODO - 4J see how input entity vector is set up and decide what way is best // to pass this to the function Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - CRITICAL_SECTION& globalRenderableTileEntities_cs, int x, int y, + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, ClipChunk* clipChunk) : globalRenderableTileEntities(&globalRenderableTileEntities), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs) { @@ -149,31 +150,31 @@ void Chunk::setPos(int x, int y, int z) { assigned = true; - EnterCriticalSection(&levelRenderer->m_csDirtyChunks); - unsigned char refCount = - levelRenderer->incGlobalChunkRefCount(x, y, z, level); - // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); + { + std::lock_guard lock(levelRenderer->m_csDirtyChunks); + unsigned char refCount = + levelRenderer->incGlobalChunkRefCount(x, y, z, level); + // printf("\t\t [inc] refcount %d at %d, %d, %d\n",refCount,x,y,z); - // int idx = levelRenderer->getGlobalIndexForChunk(x, y, z, level); + // int idx = levelRenderer->getGlobalIndexForChunk(x, y, z, level); - // If we're the first thing to be referencing this, mark it up as dirty to - // get rebuilt - if (refCount == 1) { - // printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx); - // Chunks being made dirty in this way can be very numerous (eg the full - // visible area of the world at start up, or a whole edge of the world - // when moving). On account of this, don't want to stick them into our - // lock free queue that we would normally use for letting the render - // update thread know about this chunk. Instead, just set the flag to - // say this is dirty, and then pass a special value of 1 through to the - // lock free stack which lets that thread know that at least one chunk - // other than the ones in the stack itself have been made dirty. - levelRenderer->setGlobalChunkFlag(x, y, z, level, - LevelRenderer::CHUNK_FLAG_DIRTY); - PIXSetMarkerDeprecated(0, "Non-stack event pushed"); + // If we're the first thing to be referencing this, mark it up as dirty to + // get rebuilt + if (refCount == 1) { + // printf("Setting %d %d %d dirty [%d]\n",x,y,z, idx); + // Chunks being made dirty in this way can be very numerous (eg the full + // visible area of the world at start up, or a whole edge of the world + // when moving). On account of this, don't want to stick them into our + // lock free queue that we would normally use for letting the render + // update thread know about this chunk. Instead, just set the flag to + // say this is dirty, and then pass a special value of 1 through to the + // lock free stack which lets that thread know that at least one chunk + // other than the ones in the stack itself have been made dirty. + levelRenderer->setGlobalChunkFlag(x, y, z, level, + LevelRenderer::CHUNK_FLAG_DIRTY); + PIXSetMarkerDeprecated(0, "Non-stack event pushed"); + } } - - LeaveCriticalSection(&levelRenderer->m_csDirtyChunks); } void Chunk::translateToPos() { @@ -533,9 +534,10 @@ void Chunk::rebuild() { // globally in the levelrenderer, in a hashmap with a special key made up // from the dimension and chunk position (using same index as is used for // global flags) - EnterCriticalSection(globalRenderableTileEntities_cs); - reconcileRenderableTileEntities(renderableTileEntities); - LeaveCriticalSection(globalRenderableTileEntities_cs); + { + std::lock_guard lock(*globalRenderableTileEntities_cs); + reconcileRenderableTileEntities(renderableTileEntities); + } PIXEndNamedEvent(); // 4J - These removed items are now also removed from @@ -710,27 +712,28 @@ void Chunk::reset() { int oldKey = -1; bool retireRenderableTileEntities = false; - EnterCriticalSection(&levelRenderer->m_csDirtyChunks); - oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); - unsigned char refCount = - levelRenderer->decGlobalChunkRefCount(x, y, z, level); - assigned = false; - // printf("\t\t [dec] refcount %d at %d, %d, - //%d\n",refCount,x,y,z); - if (refCount == 0 && oldKey != -1) { - retireRenderableTileEntities = true; - int lists = oldKey * 2; - if (lists >= 0) { - lists += levelRenderer->chunkLists; - for (int i = 0; i < 2; i++) { - // 4J - added - clear any renderer data associated with this - // unused list - RenderManager.CBuffClear(lists + i); + { + std::lock_guard lock(levelRenderer->m_csDirtyChunks); + oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level); + unsigned char refCount = + levelRenderer->decGlobalChunkRefCount(x, y, z, level); + assigned = false; + // printf("\t\t [dec] refcount %d at %d, %d, + //%d\n",refCount,x,y,z); + if (refCount == 0 && oldKey != -1) { + retireRenderableTileEntities = true; + int lists = oldKey * 2; + if (lists >= 0) { + lists += levelRenderer->chunkLists; + for (int i = 0; i < 2; i++) { + // 4J - added - clear any renderer data associated with this + // unused list + RenderManager.CBuffClear(lists + i); + } + levelRenderer->setGlobalChunkFlags(x, y, z, level, 0); } - levelRenderer->setGlobalChunkFlags(x, y, z, level, 0); } } - LeaveCriticalSection(&levelRenderer->m_csDirtyChunks); if (retireRenderableTileEntities) { levelRenderer->retireRenderableTileEntitiesForChunkKey(oldKey); diff --git a/Minecraft.Client/Rendering/Chunk.h b/Minecraft.Client/Rendering/Chunk.h index ea24723b7..a73808eeb 100644 --- a/Minecraft.Client/Rendering/Chunk.h +++ b/Minecraft.Client/Rendering/Chunk.h @@ -56,12 +56,12 @@ public: private: LevelRenderer::rteMap* globalRenderableTileEntities; - CRITICAL_SECTION* globalRenderableTileEntities_cs; + std::mutex* globalRenderableTileEntities_cs; bool assigned; public: Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities, - CRITICAL_SECTION& globalRenderableTileEntities_cs, int x, int y, + std::mutex& globalRenderableTileEntities_cs, int x, int y, int z, ClipChunk* clipChunk); Chunk(); diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp index e90405934..616f770a8 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.cpp @@ -4,7 +4,7 @@ #include "ProgressRenderer.h" #include "../../../Minecraft.World/Platform/System.h" -CRITICAL_SECTION ProgressRenderer::s_progress; +std::mutex ProgressRenderer::s_progress; ProgressRenderer::ProgressRenderer(Minecraft* minecraft) { status = -1; @@ -33,10 +33,11 @@ void ProgressRenderer::_progressStart(int title) { // throw new StopGameException(); // 4J - removed } - EnterCriticalSection(&ProgressRenderer::s_progress); - lastPercent = 0; - this->title = title; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + lastPercent = 0; + this->title = title; + } } @@ -47,10 +48,11 @@ void ProgressRenderer::progressStage(int status) { } lastTime = 0; - EnterCriticalSection(&ProgressRenderer::s_progress); - setType(eProgressStringType_ID); - this->status = status; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + m_eType = eProgressStringType_ID; + this->status = status; + } progressStagePercentage(-1); lastTime = 0; } @@ -58,57 +60,62 @@ void ProgressRenderer::progressStage(int status) { void ProgressRenderer::progressStagePercentage(int i) { // 4J Stu - Removing all progressRenderer rendering. This will be replaced // on the xbox - EnterCriticalSection(&ProgressRenderer::s_progress); - lastPercent = i; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + lastPercent = i; + } } int ProgressRenderer::getCurrentPercent() { int returnValue = 0; - EnterCriticalSection(&ProgressRenderer::s_progress); - returnValue = lastPercent; - LeaveCriticalSection(&ProgressRenderer::s_progress); + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = lastPercent; + } return returnValue; } int ProgressRenderer::getCurrentTitle() { - EnterCriticalSection(&ProgressRenderer::s_progress); - int returnValue = title; - LeaveCriticalSection(&ProgressRenderer::s_progress); + int returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = title; + } return returnValue; } int ProgressRenderer::getCurrentStatus() { - EnterCriticalSection(&ProgressRenderer::s_progress); - int returnValue = status; - LeaveCriticalSection(&ProgressRenderer::s_progress); + int returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = status; + } return returnValue; } ProgressRenderer::eProgressStringType ProgressRenderer::getType() { - EnterCriticalSection(&ProgressRenderer::s_progress); - eProgressStringType returnValue = m_eType; - LeaveCriticalSection(&ProgressRenderer::s_progress); + eProgressStringType returnValue; + { + std::lock_guard lock(ProgressRenderer::s_progress); + returnValue = m_eType; + } return returnValue; } void ProgressRenderer::setType(eProgressStringType eType) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_eType = eType; - LeaveCriticalSection(&ProgressRenderer::s_progress); } void ProgressRenderer::progressStage(std::wstring& wstrText) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); m_wstrText = wstrText; - setType(eProgressStringType_String); - LeaveCriticalSection(&ProgressRenderer::s_progress); + m_eType = eProgressStringType_String; } std::wstring& ProgressRenderer::getProgressString(void) { - EnterCriticalSection(&ProgressRenderer::s_progress); + std::lock_guard lock(ProgressRenderer::s_progress); std::wstring& temp = m_wstrText; - LeaveCriticalSection(&ProgressRenderer::s_progress); return temp; } diff --git a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h index 978ffeefc..97d35f0ef 100644 --- a/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h +++ b/Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../../../Minecraft.World/Util/ProgressListener.h" class ProgressRenderer : public ProgressListener { @@ -9,7 +10,7 @@ public: // on a save transfer }; - static CRITICAL_SECTION s_progress; + static std::mutex s_progress; int getCurrentPercent(); int getCurrentTitle(); diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp index fc429f5c2..bbd65503c 100644 --- a/Minecraft.Client/Rendering/GameRenderer.cpp +++ b/Minecraft.Client/Rendering/GameRenderer.cpp @@ -66,7 +66,7 @@ std::vector GameRenderer::m_deleteStackCompressedTileStorage; std::vector GameRenderer::m_deleteStackSparseDataStorage; #endif -CRITICAL_SECTION GameRenderer::m_csDeleteStack; +std::mutex GameRenderer::m_csDeleteStack; ResourceLocation GameRenderer::RAIN_LOCATION = ResourceLocation(TN_ENVIRONMENT_RAIN); @@ -170,7 +170,6 @@ GameRenderer::GameRenderer(Minecraft* mc) { eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); m_updateEvents->Set(eUpdateEventIsFinished); - InitializeCriticalSection(&m_csDeleteStack); m_updateThread = new C4JThread(runUpdate, nullptr, "Chunk update"); m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); m_updateThread->Run(); @@ -1045,27 +1044,27 @@ void GameRenderer::renderLevel(float a) { renderLevel(a, 0); } #if defined(MULTITHREAD_ENABLE) // Request that an item be deleted, when it is safe to do so void GameRenderer::AddForDelete(uint8_t* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackByte.push_back(deleteThis); } void GameRenderer::AddForDelete(SparseLightStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackSparseLightStorage.push_back(deleteThis); } void GameRenderer::AddForDelete(CompressedTileStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackCompressedTileStorage.push_back(deleteThis); } void GameRenderer::AddForDelete(SparseDataStorage* deleteThis) { - EnterCriticalSection(&m_csDeleteStack); + m_csDeleteStack.lock(); m_deleteStackSparseDataStorage.push_back(deleteThis); } void GameRenderer::FinishedReassigning() { - LeaveCriticalSection(&m_csDeleteStack); + m_csDeleteStack.unlock(); } int GameRenderer::runUpdate(void* lpParam) { @@ -1124,22 +1123,24 @@ int GameRenderer::runUpdate(void* lpParam) { // We've got stacks for things that can only safely be deleted whilst // this thread isn't updating things - delete those things now - EnterCriticalSection(&m_csDeleteStack); - for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) - delete m_deleteStackByte[i]; - m_deleteStackByte.clear(); - for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); - i++) - delete m_deleteStackSparseLightStorage[i]; - m_deleteStackSparseLightStorage.clear(); - for (unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size(); - i++) - delete m_deleteStackCompressedTileStorage[i]; - m_deleteStackCompressedTileStorage.clear(); - for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++) - delete m_deleteStackSparseDataStorage[i]; - m_deleteStackSparseDataStorage.clear(); - LeaveCriticalSection(&m_csDeleteStack); + { + std::lock_guard lock(m_csDeleteStack); + for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) + delete m_deleteStackByte[i]; + m_deleteStackByte.clear(); + for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); + i++) + delete m_deleteStackSparseLightStorage[i]; + m_deleteStackSparseLightStorage.clear(); + for (unsigned int i = 0; + i < m_deleteStackCompressedTileStorage.size(); i++) + delete m_deleteStackCompressedTileStorage[i]; + m_deleteStackCompressedTileStorage.clear(); + for (unsigned int i = 0; + i < m_deleteStackSparseDataStorage.size(); i++) + delete m_deleteStackSparseDataStorage[i]; + m_deleteStackSparseDataStorage.clear(); + } // PIXEndNamedEvent(); diff --git a/Minecraft.Client/Rendering/GameRenderer.h b/Minecraft.Client/Rendering/GameRenderer.h index 0659f53af..c92136b3b 100644 --- a/Minecraft.Client/Rendering/GameRenderer.h +++ b/Minecraft.Client/Rendering/GameRenderer.h @@ -9,6 +9,7 @@ class SparseLightStorage; class CompressedTileStorage; class SparseDataStorage; +#include #include "../../Minecraft.World/Util/SmoothFloat.h" #include "../../Minecraft.World/Util/C4JThread.h" #include "../Textures/ResourceLocation.h" @@ -191,7 +192,7 @@ public: static std::vector m_deleteStackCompressedTileStorage; static std::vector m_deleteStackSparseDataStorage; - static CRITICAL_SECTION m_csDeleteStack; + static std::mutex m_csDeleteStack; static void AddForDelete(uint8_t* deleteThis); static void AddForDelete(SparseLightStorage* deleteThis); static void AddForDelete(CompressedTileStorage* deleteThis); diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index 38405101d..293bbaca6 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "../Platform/stdafx.h" #include "LevelRenderer.h" @@ -163,11 +164,7 @@ LevelRenderer::LevelRenderer(Minecraft* mc, Textures* textures) { lastPlayerCount[i] = 0; } - InitializeCriticalSection(&m_csDirtyChunks); - InitializeCriticalSection(&m_csRenderableTileEntities); -#if defined(_LARGE_WORLDS) - InitializeCriticalSection(&m_csChunkFlags); -#endif + // std::mutex members are default-constructed dirtyChunkPresent = false; lastDirtyChunkFound = 0; @@ -395,10 +392,11 @@ void LevelRenderer::setLevel(int playerIndex, MultiPlayerLevel* level) { // actually exiting the game, so only when the primary player sets there // level to nullptr if (playerIndex == ProfileManager.GetPrimaryPad()) { - EnterCriticalSection(&m_csRenderableTileEntities); - renderableTileEntities.clear(); - m_renderableTileEntitiesPendingRemoval.clear(); - LeaveCriticalSection(&m_csRenderableTileEntities); + { + std::lock_guard lock(m_csRenderableTileEntities); + renderableTileEntities.clear(); + m_renderableTileEntitiesPendingRemoval.clear(); + } } } } @@ -428,7 +426,6 @@ void LevelRenderer::allChanged(int playerIndex) { // to add it back then: If this CS is entered before DisableUpdateThread is // called then (on 360 at least) we can get a deadlock when starting a game // in splitscreen. - // EnterCriticalSection(&m_csDirtyChunks); if (level[playerIndex] == nullptr) { return; } @@ -517,8 +514,6 @@ void LevelRenderer::allChanged(int playerIndex) { Minecraft::GetInstance()->gameRenderer->EnableUpdateThread(); - // 4J Stu - Remove. See comment above. - // LeaveCriticalSection(&m_csDirtyChunks); } void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { @@ -619,21 +614,21 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) { // 4J - have restructed this so that the tile entities are stored within a // hashmap by chunk/dimension index. The index is calculated in the same way // as the global flags. - EnterCriticalSection(&m_csRenderableTileEntities); - for (auto it = renderableTileEntities.begin(); - it != renderableTileEntities.end(); it++) { - int idx = it->first; - // Don't render if it isn't in the same dimension as this player - if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue; + { + std::lock_guard lock(m_csRenderableTileEntities); + for (auto it = renderableTileEntities.begin(); + it != renderableTileEntities.end(); it++) { + int idx = it->first; + // Don't render if it isn't in the same dimension as this player + if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue; - for (auto it2 = it->second.tiles.begin(); - it2 != it->second.tiles.end(); it2++) { - TileEntityRenderDispatcher::instance->render(*it2, a); + for (auto it2 = it->second.tiles.begin(); + it2 != it->second.tiles.end(); it2++) { + TileEntityRenderDispatcher::instance->render(*it2, a); + } } } - LeaveCriticalSection(&m_csRenderableTileEntities); - mc->gameRenderer->turnOffLightLayer(a); // 4J - brought forward from 1.8.2 } @@ -653,7 +648,7 @@ std::wstring LevelRenderer::gatherStats2() { } void LevelRenderer::resortChunks(int xc, int yc, int zc) { - EnterCriticalSection(&m_csDirtyChunks); + std::lock_guard lock(m_csDirtyChunks); xc -= CHUNK_XZSIZE / 2; yc -= CHUNK_SIZE / 2; zc -= CHUNK_XZSIZE / 2; @@ -702,7 +697,6 @@ void LevelRenderer::resortChunks(int xc, int yc, int zc) { } } nonStackDirtyChunksAdded(); - LeaveCriticalSection(&m_csDirtyChunks); } int LevelRenderer::render(std::shared_ptr player, int layer, @@ -1730,7 +1724,7 @@ bool LevelRenderer::updateDirtyChunks() { PIXAddNamedCounter(((float)memAlloc) / (1024.0f * 1024.0f), "Command buffer allocations"); bool onlyRebuild = (memAlloc >= MAX_COMMANDBUFFER_ALLOCATIONS); - EnterCriticalSection(&m_csDirtyChunks); + std::unique_lock dirtyChunksLock(m_csDirtyChunks); // Move any dirty chunks stored in the lock free stack into global flags int index = 0; @@ -1952,7 +1946,7 @@ bool LevelRenderer::updateDirtyChunks() { permaChunk[index].makeCopyForRebuild(chunk); ++index; } - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); --index; // Bring it back into 0 counted range @@ -2043,7 +2037,7 @@ bool LevelRenderer::updateDirtyChunks() { // this copy. The copy will then be guaranteed to be consistent // whilst rebuilding takes place outside of that critical section. permaChunk.makeCopyForRebuild(chunk); - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); } // static int64_t totalTime = 0; // static int64_t countTime = 0; @@ -2070,7 +2064,7 @@ bool LevelRenderer::updateDirtyChunks() { } else { dirtyChunkPresent = false; } - LeaveCriticalSection(&m_csDirtyChunks); + dirtyChunksLock.unlock(); return false; } @@ -2295,7 +2289,6 @@ void LevelRenderer::setDirty(int x0, int y0, int z0, int x1, int y1, int z1, // come from when connection is being ticked outside of normal level tick, // and player won't be set up if (level == nullptr) level = this->level[mc->player->GetXboxPad()]; - // EnterCriticalSection(&m_csDirtyChunks); int _x0 = Mth::intFloorDiv(x0, CHUNK_XZSIZE); int _y0 = Mth::intFloorDiv(y0, CHUNK_SIZE); int _z0 = Mth::intFloorDiv(z0, CHUNK_XZSIZE); @@ -2385,7 +2378,6 @@ void LevelRenderer::setDirty(int x0, int y0, int z0, int x1, int y1, int z1, } } } - // LeaveCriticalSection(&m_csDirtyChunks); } void LevelRenderer::tileChanged(int x, int y, int z) { @@ -3687,12 +3679,9 @@ void LevelRenderer::setGlobalChunkFlags(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] = flags; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3702,12 +3691,9 @@ void LevelRenderer::setGlobalChunkFlag(int index, unsigned char flag, if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] |= sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3718,12 +3704,9 @@ void LevelRenderer::setGlobalChunkFlag(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] |= sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3747,12 +3730,9 @@ void LevelRenderer::clearGlobalChunkFlag(int x, int y, int z, Level* level, int index = getGlobalIndexForChunk(x, y, z, level); if (index != -1) { #if defined(_LARGE_WORLDS) - EnterCriticalSection(&m_csChunkFlags); + std::lock_guard lock(m_csChunkFlags); #endif globalChunkFlags[index] &= ~sflag; -#if defined(_LARGE_WORLDS) - LeaveCriticalSection(&m_csChunkFlags); -#endif } } @@ -3844,19 +3824,19 @@ void LevelRenderer::eraseRenderableTileEntity_Locked( void LevelRenderer::retireRenderableTileEntitiesForChunkKey(int key) { if (key == -1) return; - EnterCriticalSection(&m_csRenderableTileEntities); - renderableTileEntities.erase(key); - m_renderableTileEntitiesPendingRemoval.erase(key); - LeaveCriticalSection(&m_csRenderableTileEntities); + { + std::lock_guard lock(m_csRenderableTileEntities); + renderableTileEntities.erase(key); + m_renderableTileEntitiesPendingRemoval.erase(key); + } } // 4J added void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() { FRAME_PROFILE_SCOPE(RenderableTileEntityCleanup); - EnterCriticalSection(&m_csRenderableTileEntities); + std::lock_guard lock(m_csRenderableTileEntities); if (m_renderableTileEntitiesPendingRemoval.empty()) { - LeaveCriticalSection(&m_csRenderableTileEntities); return; } @@ -3886,7 +3866,6 @@ void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() { } } m_renderableTileEntitiesPendingRemoval.clear(); - LeaveCriticalSection(&m_csRenderableTileEntities); } LevelRenderer::DestroyedTileManager::RecentTile::RecentTile(int x, int y, int z, @@ -3897,11 +3876,10 @@ LevelRenderer::DestroyedTileManager::RecentTile::RecentTile(int x, int y, int z, } LevelRenderer::DestroyedTileManager::DestroyedTileManager() { - InitializeCriticalSection(&m_csDestroyedTiles); + // std::mutex is default-constructed } LevelRenderer::DestroyedTileManager::~DestroyedTileManager() { - DeleteCriticalSection(&m_csDestroyedTiles); for (unsigned int i = 0; i < m_destroyedTiles.size(); i++) { delete m_destroyedTiles[i]; } @@ -3911,7 +3889,7 @@ LevelRenderer::DestroyedTileManager::~DestroyedTileManager() { // be called before it actually is) void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, int y, int z) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // Store a list of AABBs that the tile to be destroyed would have made, // before we go and destroy it. This is made slightly more complicated as @@ -3928,8 +3906,6 @@ void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, } m_destroyedTiles.push_back(recentTile); - - LeaveCriticalSection(&m_csDestroyedTiles); } // For chunk rebuilding to inform the manager that a chunk (a 16x16x16 tile @@ -3937,7 +3913,7 @@ void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x, void LevelRenderer::DestroyedTileManager::updatedChunkAt(Level* level, int x, int y, int z, int veryNearCount) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // There's 2 stages to this. This function is called when a renderer chunk // has been rebuilt, but that chunk's render data might be grouped @@ -3979,15 +3955,13 @@ void LevelRenderer::DestroyedTileManager::updatedChunkAt(Level* level, int x, } } } - - LeaveCriticalSection(&m_csDestroyedTiles); } // For game to get any AABBs that the user should be colliding with as render // data has not yet been updated void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box, AABBList* boxes) { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); for (unsigned int i = 0; i < m_destroyedTiles.size(); i++) { if (m_destroyedTiles[i]->level == level) { @@ -4009,11 +3983,10 @@ void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box, } } - LeaveCriticalSection(&m_csDestroyedTiles); } void LevelRenderer::DestroyedTileManager::tick() { - EnterCriticalSection(&m_csDestroyedTiles); + std::lock_guard lock(m_csDestroyedTiles); // Remove any tiles that have timed out for (unsigned int i = 0; i < m_destroyedTiles.size();) { @@ -4025,8 +3998,6 @@ void LevelRenderer::DestroyedTileManager::tick() { i++; } } - - LeaveCriticalSection(&m_csDestroyedTiles); } #if defined(_LARGE_WORLDS) diff --git a/Minecraft.Client/Rendering/LevelRenderer.h b/Minecraft.Client/Rendering/LevelRenderer.h index 006d357f4..7e187e998 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.h +++ b/Minecraft.Client/Rendering/LevelRenderer.h @@ -8,6 +8,7 @@ #include #endif #include +#include class MultiPlayerLevel; class Textures; class Chunk; @@ -164,7 +165,7 @@ private: typedef std::unordered_map rtePendingRemovalMap; rtePendingRemovalMap m_renderableTileEntitiesPendingRemoval; - CRITICAL_SECTION m_csRenderableTileEntities; + std::mutex m_csRenderableTileEntities; MultiPlayerLevel* level[4]; // 4J - now one per player Textures* textures; // std::vector *sortedChunks[4]; // 4J - removed - not @@ -215,7 +216,7 @@ private: public: void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added - CRITICAL_SECTION m_csDirtyChunks; + std::mutex m_csDirtyChunks; bool m_nearDirtyChunk; // 4J - Destroyed Tile Management - these things added so we can track tiles @@ -235,7 +236,7 @@ public: RecentTile(int x, int y, int z, Level* level); ~RecentTile() = default; }; - CRITICAL_SECTION m_csDestroyedTiles; + std::mutex m_csDestroyedTiles; std::vector m_destroyedTiles; public: @@ -343,7 +344,7 @@ public: static void staticCtor(); static int rebuildChunkThreadProc(void* lpParam); - CRITICAL_SECTION m_csChunkFlags; + std::mutex m_csChunkFlags; #endif void nonStackDirtyChunksAdded(); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp index 7abb318cf..eaafbcc2d 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp @@ -777,11 +777,11 @@ int ConsoleSaveFileOriginal::getOriginalSaveVersion() { } void ConsoleSaveFileOriginal::LockSaveAccess() { - EnterCriticalSection(&m_lock); + m_lock.lock(); } void ConsoleSaveFileOriginal::ReleaseSaveAccess() { - LeaveCriticalSection(&m_lock); + m_lock.unlock(); } ESavePlatform ConsoleSaveFileOriginal::getSavePlatform() { diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h index 7ca7e7cf6..eaada76a9 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.h @@ -1,4 +1,5 @@ #pragma once +#include #include "FileHeader.h" #include "ConsoleSavePath.h" @@ -23,7 +24,7 @@ private: #endif void* pvSaveMem; - CRITICAL_SECTION m_lock; + std::mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp index 31bc923f1..8f4b16446 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp @@ -397,7 +397,6 @@ ConsoleSaveFileSplit::ConsoleSaveFileSplit(ConsoleSaveFile* sourceSave, void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData, unsigned int fileSize, ESavePlatform plat) { - InitializeCriticalSectionAndSpinCount(&m_lock, 5120); m_lastTickTime = 0; @@ -550,7 +549,6 @@ ConsoleSaveFileSplit::~ConsoleSaveFileSplit() { } StorageManager.ResetSubfiles(); - DeleteCriticalSection(&m_lock); } // Add the file to our table of internal files if not already there @@ -1508,10 +1506,10 @@ int ConsoleSaveFileSplit::getOriginalSaveVersion() { return header.getOriginalSaveVersion(); } -void ConsoleSaveFileSplit::LockSaveAccess() { EnterCriticalSection(&m_lock); } +void ConsoleSaveFileSplit::LockSaveAccess() { m_lock.lock(); } void ConsoleSaveFileSplit::ReleaseSaveAccess() { - LeaveCriticalSection(&m_lock); + m_lock.unlock(); } ESavePlatform ConsoleSaveFileSplit::getSavePlatform() { diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h index 971d859b5..701f17895 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.h @@ -1,4 +1,5 @@ #pragma once +#include #include "FileHeader.h" #include "ConsoleSavePath.h" @@ -79,7 +80,7 @@ private: #endif void* pvSaveMem; - CRITICAL_SECTION m_lock; + std::mutex m_lock; void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite); void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite); diff --git a/Minecraft.World/IO/Streams/Compression.cpp b/Minecraft.World/IO/Streams/Compression.cpp index da7662638..656724fa8 100644 --- a/Minecraft.World/IO/Streams/Compression.cpp +++ b/Minecraft.World/IO/Streams/Compression.cpp @@ -41,7 +41,7 @@ Compression* Compression::getCompression() { int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleCompressLock); + std::lock_guard lock(rleCompressLock); // static unsigned char rleBuf[1024*100]; unsigned char* pucIn = (unsigned char*)pSource; @@ -83,7 +83,6 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, PIXBeginNamedEvent(0, "Secondary compression"); Compress(pDestination, pDestSize, rleCompressBuf, rleSize); PIXEndNamedEvent(); - LeaveCriticalSection(&rleCompressLock); // printf("Compressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize); return S_OK; @@ -91,7 +90,8 @@ int32_t Compression::CompressLZXRLE(void* pDestination, unsigned int* pDestSize, int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleCompressLock); + unsigned int rleSize; + { std::lock_guard lock(rleCompressLock); // static unsigned char rleBuf[1024*100]; unsigned char* pucIn = (unsigned char*)pSource; @@ -127,9 +127,9 @@ int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, *pucOut++ = thisOne; } } while (pucIn != pucEnd); - unsigned int rleSize = (unsigned int)(pucOut - rleCompressBuf); + rleSize = (unsigned int)(pucOut - rleCompressBuf); PIXEndNamedEvent(); - LeaveCriticalSection(&rleCompressLock); + } // Return if (rleSize <= *pDestSize) { @@ -147,7 +147,7 @@ int32_t Compression::CompressRLE(void* pDestination, unsigned int* pDestSize, int32_t Compression::DecompressLZXRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleDecompressLock); + std::lock_guard lock(rleDecompressLock); // 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world // after updating TU Some saves can have chunks that decompress into very // large sizes, so I have doubled the size of this buffer Ideally we should @@ -203,13 +203,12 @@ int32_t Compression::DecompressLZXRLE(void* pDestination, if (dynamicRleBuf != nullptr) delete[] dynamicRleBuf; - LeaveCriticalSection(&rleDecompressLock); return S_OK; } int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize, void* pSource, unsigned int SrcSize) { - EnterCriticalSection(&rleDecompressLock); + std::lock_guard lock(rleDecompressLock); // unsigned char *pucIn = (unsigned char *)rleDecompressBuf; unsigned char* pucIn = (unsigned char*)pSource; @@ -238,7 +237,6 @@ int32_t Compression::DecompressRLE(void* pDestination, unsigned int* pDestSize, } *pDestSize = (unsigned int)(pucOut - (unsigned char*)pDestination); - LeaveCriticalSection(&rleDecompressLock); return S_OK; } @@ -439,17 +437,12 @@ Compression::Compression() { m_localDecompressType = eCompressionType_ZLIBRLE; m_decompressType = m_localDecompressType; - - InitializeCriticalSection(&rleCompressLock); - InitializeCriticalSection(&rleDecompressLock); } Compression::~Compression() { XMemDestroyCompressionContext(compressionContext); XMemDestroyDecompressionContext(decompressionContext); - DeleteCriticalSection(&rleCompressLock); - DeleteCriticalSection(&rleDecompressLock); } void Compression::SetDecompressionType(ESavePlatform platform) { diff --git a/Minecraft.World/IO/Streams/Compression.h b/Minecraft.World/IO/Streams/Compression.h index 980c9e6b1..2ff65a491 100644 --- a/Minecraft.World/IO/Streams/Compression.h +++ b/Minecraft.World/IO/Streams/Compression.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Files/FileHeader.h" class Compression { @@ -67,8 +68,8 @@ private: XMEMCOMPRESSION_CONTEXT compressionContext; XMEMDECOMPRESSION_CONTEXT decompressionContext; - CRITICAL_SECTION rleCompressLock; - CRITICAL_SECTION rleDecompressLock; + std::mutex rleCompressLock; + std::mutex rleDecompressLock; unsigned char rleCompressBuf[1024 * 100]; static const unsigned int staticRleSize = 1024 * 200; diff --git a/Minecraft.World/Level/Level.cpp b/Minecraft.World/Level/Level.cpp index 2a1870696..0f3a29a3d 100644 --- a/Minecraft.World/Level/Level.cpp +++ b/Minecraft.World/Level/Level.cpp @@ -27,6 +27,7 @@ #include "../Util/WeighedRandom.h" #include "../IO/Files/ConsoleSaveFile.h" +#include #include #include "../../Minecraft.Client/Minecraft.h" #include "../../Minecraft.Client/Rendering/LevelRenderer.h" @@ -539,17 +540,12 @@ void Level::_init() { isClientSide = false; - InitializeCriticalSection(&m_entitiesCS); - InitializeCriticalSection(&m_tileEntityListCS); - updatingTileEntities = false; villageSiege = new VillageSiege(this); scoreboard = new Scoreboard(); toCheckLevel = new int[32 * 32 * 32]; // 4J - brought forward from 1.8.2 - InitializeCriticalSectionAndSpinCount( - &m_checkLightCS, 5120); // 4J - added for 1.8.2 lighting // 4J Added m_bDisableAddNewTileEntities = false; @@ -699,16 +695,11 @@ Level::~Level() { NotGateTile::removeLevelReferences(this); // 4J added } - DeleteCriticalSection(&m_checkLightCS); - // 4J-PB - savedDataStorage is shared between overworld and nether levels in // the server, so it will already have been deleted on the first level // delete if (savedDataStorage != nullptr) delete savedDataStorage; - DeleteCriticalSection(&m_entitiesCS); - DeleteCriticalSection(&m_tileEntityListCS); - // 4J Stu - At least one of the listeners is something we cannot delete, the // LevelRenderer /* @@ -1622,11 +1613,11 @@ bool Level::addEntity(std::shared_ptr e) { MemSect(42); getChunk(xc, zc)->addEntity(e); MemSect(0); - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); MemSect(43); entities.push_back(e); MemSect(0); - LeaveCriticalSection(&m_entitiesCS); + } MemSect(44); entityAdded(e); MemSect(0); @@ -1707,7 +1698,7 @@ void Level::removeEntityImmediately(std::shared_ptr e) { getChunk(xc, zc)->removeEntity(e); } - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); std::vector >::iterator it = entities.begin(); std::vector >::iterator endIt = entities.end(); while (it != endIt && *it != e) it++; @@ -1715,7 +1706,7 @@ void Level::removeEntityImmediately(std::shared_ptr e) { if (it != endIt) { entities.erase(it); } - LeaveCriticalSection(&m_entitiesCS); + } entityRemoved(e); } @@ -2084,7 +2075,7 @@ void Level::tickEntities() { } } - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); for (auto it = entities.begin(); it != entities.end();) { bool found = false; @@ -2101,7 +2092,7 @@ void Level::tickEntities() { it++; } } - LeaveCriticalSection(&m_entitiesCS); + } auto itETREnd = entitiesToRemove.end(); for (auto it = entitiesToRemove.begin(); it != itETREnd; it++) { @@ -2125,7 +2116,7 @@ void Level::tickEntities() { /* 4J Jev, using an iterator causes problems here as * the vector is modified from inside this loop. */ - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); for (unsigned int i = 0; i < entities.size();) { std::shared_ptr e = entities.at(i); @@ -2171,9 +2162,9 @@ void Level::tickEntities() { i++; } } - LeaveCriticalSection(&m_entitiesCS); + } - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); updatingTileEntities = true; for (auto it = tileEntityList.begin(); it != tileEntityList.end();) { @@ -2243,12 +2234,12 @@ void Level::tickEntities() { } pendingTileEntities.clear(); } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::addAllPendingTileEntities( std::vector >& entities) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); if (updatingTileEntities) { for (auto it = entities.begin(); it != entities.end(); it++) { pendingTileEntities.push_back(*it); @@ -2258,7 +2249,7 @@ void Level::addAllPendingTileEntities( tileEntityList.push_back(*it); } } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::tick(std::shared_ptr e) { tick(e, true); } @@ -2598,9 +2589,9 @@ return shared_ptr(); std::wstring Level::gatherStats() { wchar_t buf[64]; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); swprintf(buf, 64, L"All:%d", entities.size()); - LeaveCriticalSection(&m_entitiesCS); + } return std::wstring(buf); } @@ -2615,7 +2606,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { std::shared_ptr tileEntity = nullptr; if (updatingTileEntities) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); for (int i = 0; i < pendingTileEntities.size(); i++) { std::shared_ptr e = pendingTileEntities.at(i); if (!e->isRemoved() && e->x == x && e->y == y && e->z == z) { @@ -2623,7 +2614,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { break; } } - LeaveCriticalSection(&m_tileEntityListCS); + } } if (tileEntity == nullptr) { @@ -2634,7 +2625,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { } if (tileEntity == nullptr) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); for (auto it = pendingTileEntities.begin(); it != pendingTileEntities.end(); it++) { std::shared_ptr e = *it; @@ -2644,7 +2635,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { break; } } - LeaveCriticalSection(&m_tileEntityListCS); + } } return tileEntity; } @@ -2652,7 +2643,7 @@ std::shared_ptr Level::getTileEntity(int x, int y, int z) { void Level::setTileEntity(int x, int y, int z, std::shared_ptr tileEntity) { if (tileEntity != nullptr && !tileEntity->isRemoved()) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); if (updatingTileEntities) { tileEntity->x = x; tileEntity->y = y; @@ -2677,12 +2668,12 @@ void Level::setTileEntity(int x, int y, int z, LevelChunk* lc = getChunk(x >> 4, z >> 4); if (lc != nullptr) lc->setTileEntity(x & 15, y, z & 15, tileEntity); } - LeaveCriticalSection(&m_tileEntityListCS); + } } } void Level::removeTileEntity(int x, int y, int z) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); std::shared_ptr te = getTileEntity(x, y, z); if (te != nullptr && updatingTileEntities) { te->setRemoved(); @@ -2707,13 +2698,13 @@ void Level::removeTileEntity(int x, int y, int z) { LevelChunk* lc = getChunk(x >> 4, z >> 4); if (lc != nullptr) lc->removeTileEntity(x & 15, y, z & 15); } - LeaveCriticalSection(&m_tileEntityListCS); + } } void Level::markForRemoval(std::shared_ptr entity) { - EnterCriticalSection(&m_tileEntityListCS); + { std::lock_guard lock(m_tileEntityListCS); tileEntitiesToUnload.insert(entity); - LeaveCriticalSection(&m_tileEntityListCS); + } } bool Level::isSolidRenderTile(int x, int y, int z) { @@ -3110,7 +3101,7 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, } - EnterCriticalSection(&m_checkLightCS); + { std::lock_guard lock(m_checkLightCS); initCachePartial(cache, xc, yc, zc); @@ -3133,7 +3124,6 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, int minXZ = -(dimension->getXZSize() * 16) / 2; int maxXZ = (dimension->getXZSize() * 16) / 2 - 1; if ((xc > maxXZ) || (xc < minXZ) || (zc > maxXZ) || (zc < minXZ)) { - LeaveCriticalSection(&m_checkLightCS); return; } @@ -3338,7 +3328,7 @@ void Level::checkLight(LightLayer::variety layer, int xc, int yc, int zc, // if( cache ) XUnlockL2(XLOCKL2_INDEX_TITLE); flushCache(cache, cacheUse, layer); - LeaveCriticalSection(&m_checkLightCS); + } } bool Level::tickPendingTicks(bool force) { return false; } @@ -3423,9 +3413,8 @@ std::shared_ptr Level::getClosestEntityOfClass( } std::vector > Level::getAllEntities() { - EnterCriticalSection(&m_entitiesCS); + std::lock_guard lock(m_entitiesCS); std::vector > retVec = entities; - LeaveCriticalSection(&m_entitiesCS); return retVec; } @@ -3447,7 +3436,7 @@ unsigned int Level::countInstanceOf( unsigned int count = 0; if (protectedCount) *protectedCount = 0; if (couldWanderCount) *couldWanderCount = 0; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); auto itEnd = entities.end(); for (auto it = entities.begin(); it != itEnd; it++) { std::shared_ptr e = *it; // entities.at(i); @@ -3467,7 +3456,7 @@ unsigned int Level::countInstanceOf( if (e->instanceof(clas)) count++; } } - LeaveCriticalSection(&m_entitiesCS); + } return count; } @@ -3475,7 +3464,7 @@ unsigned int Level::countInstanceOf( unsigned int Level::countInstanceOfInRange(eINSTANCEOF clas, bool singleType, int range, int x, int y, int z) { unsigned int count = 0; - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); auto itEnd = entities.end(); for (auto it = entities.begin(); it != itEnd; it++) { std::shared_ptr e = *it; // entities.at(i); @@ -3493,14 +3482,14 @@ unsigned int Level::countInstanceOfInRange(eINSTANCEOF clas, bool singleType, if (e->instanceof(clas)) count++; } } - LeaveCriticalSection(&m_entitiesCS); + } return count; } void Level::addEntities(std::vector >* list) { // entities.addAll(list); - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); entities.insert(entities.end(), list->begin(), list->end()); auto itEnd = list->end(); bool deleteDragons = false; @@ -3528,7 +3517,7 @@ void Level::addEntities(std::vector >* list) { } } } - LeaveCriticalSection(&m_entitiesCS); + } } void Level::removeEntities(std::vector >* list) { @@ -3943,11 +3932,11 @@ void Level::ensureAdded(std::shared_ptr entity) { } // if (!entities.contains(entity)) - EnterCriticalSection(&m_entitiesCS); + { std::lock_guard lock(m_entitiesCS); if (find(entities.begin(), entities.end(), entity) == entities.end()) { entities.push_back(entity); } - LeaveCriticalSection(&m_entitiesCS); + } } bool Level::mayInteract(std::shared_ptr player, int xt, int yt, int zt, diff --git a/Minecraft.World/Level/Level.h b/Minecraft.World/Level/Level.h index a5992f429..92470c723 100644 --- a/Minecraft.World/Level/Level.h +++ b/Minecraft.World/Level/Level.h @@ -10,6 +10,7 @@ #include "../WorldGen/Biomes/Biome.h" #include "../Util/C4JThread.h" #include +#include #include // 4J Stu - This value should be big enough that we don't get any crashes causes @@ -100,7 +101,7 @@ public: static const int TICKS_PER_DAY = 20 * 60 * 20; // ORG:20*60*20 public: - CRITICAL_SECTION m_entitiesCS; // 4J added + std::recursive_mutex m_entitiesCS; // 4J added std::vector > entities; @@ -110,7 +111,7 @@ protected: public: bool hasEntitiesToRemove(); // 4J added bool m_bDisableAddNewTileEntities; // 4J Added - CRITICAL_SECTION m_tileEntityListCS; // 4J added + std::recursive_mutex m_tileEntityListCS; // 4J added std::vector > tileEntityList; private: @@ -630,7 +631,7 @@ public: virtual bool newFallingTileAllowed() { return true; } // 4J - added for new lighting from 1.8.2 - CRITICAL_SECTION m_checkLightCS; + std::recursive_mutex m_checkLightCS; private: int m_iHighestY; // 4J-PB - for the end portal in The End diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index dc8df54fc..0ffb12f8b 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -19,29 +19,25 @@ #include "../Entities/ItemEntity.h" #include "../Entities/Mobs/Minecart.h" +#include + #if defined(SHARING_ENABLED) -CRITICAL_SECTION LevelChunk::m_csSharing; +std::mutex LevelChunk::m_csSharing; #endif #if defined(_ENTITIES_RW_SECTION) // AP - use a RW critical section so we can have multiple threads reading the // same data to avoid a clash CRITICAL_RW_SECTION LevelChunk::m_csEntities; #else -CRITICAL_SECTION LevelChunk::m_csEntities; +std::mutex LevelChunk::m_csEntities; #endif -CRITICAL_SECTION LevelChunk::m_csTileEntities; +std::mutex LevelChunk::m_csTileEntities; bool LevelChunk::touchedSky = false; void LevelChunk::staticCtor() { -#if defined(SHARING_ENABLED) - InitializeCriticalSection(&m_csSharing); -#endif #if defined(_ENTITIES_RW_SECTION) InitializeCriticalRWSection(&m_csEntities); -#else - InitializeCriticalSection(&m_csEntities); #endif - InitializeCriticalSection(&m_csTileEntities); } void LevelChunk::init(Level* level, int x, int z) { @@ -52,14 +48,14 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks = new std::vector >*[ENTITY_BLOCKS_LENGTH]; #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif terrainPopulated = 0; @@ -83,7 +79,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { entityBlocks[i] = new std::vector >(); @@ -91,7 +87,7 @@ void LevelChunk::init(Level* level, int x, int z) { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif MemSect(0); @@ -253,10 +249,9 @@ void LevelChunk::setUnsaved(bool unsaved) { void LevelChunk::stopSharingTilesAndData() { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); lastUnsharedTime = System::currentTimeMillis(); if (!sharingTilesAndData) { - LeaveCriticalSection(&m_csSharing); return; } @@ -269,7 +264,6 @@ void LevelChunk::stopSharingTilesAndData() { if ((serverTerrainPopulated) && (((*serverTerrainPopulated) & sTerrainPopulatedAllAffecting) != sTerrainPopulatedAllAffecting)) { - LeaveCriticalSection(&m_csSharing); return; } @@ -277,7 +271,6 @@ void LevelChunk::stopSharingTilesAndData() { // don't drop out here we'll end up unsharing the chunk at this location for // no reason if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -311,7 +304,7 @@ void LevelChunk::stopSharingTilesAndData() { sharingTilesAndData = false; MemSect(0); - LeaveCriticalSection(&m_csSharing); + } #endif } @@ -322,10 +315,9 @@ void LevelChunk::stopSharingTilesAndData() { // not sharing void LevelChunk::reSyncLighting() { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -354,15 +346,14 @@ void LevelChunk::reSyncLighting() { upperBlockLight = new SparseLightStorage(lc->upperBlockLight); GameRenderer::FinishedReassigning(); } - LeaveCriticalSection(&m_csSharing); + } #endif } void LevelChunk::startSharingTilesAndData(int forceMs) { #if defined(SHARING_ENABLED) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { - LeaveCriticalSection(&m_csSharing); return; } @@ -371,7 +362,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { // doesn't make sense to go resharing the 0,0 block on behalf of an empty // chunk either if (isEmpty()) { - LeaveCriticalSection(&m_csSharing); return; } @@ -394,7 +384,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { if (!lowerBlocks->isSameAs(lc->lowerBlocks) || (upperBlocks && lc->upperBlocks && !upperBlocks->isSameAs(lc->upperBlocks))) { - LeaveCriticalSection(&m_csSharing); return; } } else { @@ -402,7 +391,6 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { // last wanted to unshare this chunk int64_t timenow = System::currentTimeMillis(); if ((timenow - lastUnsharedTime) < forceMs) { - LeaveCriticalSection(&m_csSharing); return; } } @@ -429,7 +417,7 @@ void LevelChunk::startSharingTilesAndData(int forceMs) { } sharingTilesAndData = true; - LeaveCriticalSection(&m_csSharing); + } #endif } @@ -1193,13 +1181,13 @@ void LevelChunk::addEntity(std::shared_ptr e) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif entityBlocks[yc]->push_back(e); #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } @@ -1214,7 +1202,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif // 4J - was entityBlocks[yc]->remove(e); @@ -1231,7 +1219,7 @@ void LevelChunk::removeEntity(std::shared_ptr e, int yc) { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } @@ -1256,14 +1244,13 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // 4J Stu - Changed as we should not be using the [] accessor (causes an // insert when we don't want one) // shared_ptr tileEntity = tileEntities[pos]; - EnterCriticalSection(&m_csTileEntities); std::shared_ptr tileEntity = nullptr; + { std::unique_lock lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it == tileEntities.end()) { - LeaveCriticalSection( - &m_csTileEntities); // Note: don't assume iterator is valid for - // tileEntities after this point + lock.unlock(); // Note: don't assume iterator is valid for + // tileEntities after this point // Fix for #48450 - All: Code Defect: Hang: Game hangs in tutorial, when // player arrive at the particular coordinate 4J Stu - Chests try to get @@ -1289,20 +1276,20 @@ std::shared_ptr LevelChunk::getTileEntity(int x, int y, int z) { // doesn't seem right - assignment wrong way? Check // 4J Stu - It should have been inserted by now, but check to be sure - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock2(m_csTileEntities); auto newIt = tileEntities.find(pos); if (newIt != tileEntities.end()) { tileEntity = newIt->second; } - LeaveCriticalSection(&m_csTileEntities); + } } else { tileEntity = it->second; - LeaveCriticalSection(&m_csTileEntities); + } } if (tileEntity != nullptr && tileEntity->isRemoved()) { - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities.erase(pos); - LeaveCriticalSection(&m_csTileEntities); + } return nullptr; } @@ -1315,9 +1302,10 @@ void LevelChunk::addTileEntity(std::shared_ptr te) { int zz = (int)(te->z - this->z * 16); setTileEntity(xx, yy, zz, te); if (loaded) { - EnterCriticalSection(&level->m_tileEntityListCS); - level->tileEntityList.push_back(te); - LeaveCriticalSection(&level->m_tileEntityListCS); + { + std::lock_guard lock(level->m_tileEntityListCS); + level->tileEntityList.push_back(te); + } } } @@ -1345,9 +1333,9 @@ void LevelChunk::setTileEntity(int x, int y, int z, tileEntity->clearRemoved(); - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); tileEntities[pos] = tileEntity; - LeaveCriticalSection(&m_csTileEntities); + } } void LevelChunk::removeTileEntity(int x, int y, int z) { @@ -1359,7 +1347,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { // if (removeThis != null) { // removeThis.setRemoved(); // } - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); auto it = tileEntities.find(pos); if (it != tileEntities.end()) { std::shared_ptr te = tileEntities[pos]; @@ -1372,7 +1360,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) { te->setRemoved(); } } - LeaveCriticalSection(&m_csTileEntities); + } } } @@ -1417,18 +1405,18 @@ void LevelChunk::load() { #endif std::vector > values; - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { values.push_back(it->second); } - LeaveCriticalSection(&m_csTileEntities); + } level->addAllPendingTileEntities(values); #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->addEntities(entityBlocks[i]); @@ -1436,7 +1424,7 @@ void LevelChunk::load() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif } else { #if defined(_LARGE_WORLDS) @@ -1450,12 +1438,12 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter loaded = false; if (unloadTileEntities) { std::vector > tileEntitiesToRemove; - EnterCriticalSection(&m_csTileEntities); + { std::lock_guard lock(m_csTileEntities); for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) { tileEntitiesToRemove.push_back(it->second); } - LeaveCriticalSection(&m_csTileEntities); + } auto itEnd = tileEntitiesToRemove.end(); for (auto it = tileEntitiesToRemove.begin(); it != itEnd; it++) { @@ -1467,7 +1455,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { level->removeEntities(entityBlocks[i]); @@ -1475,7 +1463,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif // app.DebugPrintf("Unloaded chunk %d, %d\n", x, z); @@ -1492,7 +1480,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter PIXBeginNamedEvent(0, "Saving entities"); ListTag* entityTags = new ListTag(); - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { auto itEnd = entityBlocks[i]->end(); for (std::vector >::iterator it = @@ -1508,7 +1496,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter // Clear out this list entityBlocks[i]->clear(); } - LeaveCriticalSection(&m_csEntities); + } m_unloadedEntitiesTag->put(L"Entities", entityTags); PIXEndNamedEvent(); @@ -1540,7 +1528,7 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, true); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) { std::vector >* vecEntity = entityBlocks[i]; @@ -1549,7 +1537,6 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); #endif return true; } @@ -1558,7 +1545,7 @@ bool LevelChunk::containsPlayer() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, true); #else - LeaveCriticalSection(&m_csEntities); + } #endif return false; } @@ -1579,7 +1566,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntities - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1603,7 +1590,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, } } } - LeaveCriticalSection(&m_csEntities); + } } void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, @@ -1625,7 +1612,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // AP - RW critical sections are expensive so enter once in // Level::getEntitiesOfClass - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); for (int yc = yc0; yc <= yc1; yc++) { std::vector >* entities = entityBlocks[yc]; @@ -1665,7 +1652,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, // baseClass.isAssignableFrom(e.getClass()) } } - LeaveCriticalSection(&m_csEntities); + } } int LevelChunk::countEntities() { @@ -1673,7 +1660,7 @@ int LevelChunk::countEntities() { #if defined(_ENTITIES_RW_SECTION) EnterCriticalRWSection(&m_csEntities, false); #else - EnterCriticalSection(&m_csEntities); + { std::lock_guard lock(m_csEntities); #endif for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) { entityCount += (int)entityBlocks[yc]->size(); @@ -1681,7 +1668,7 @@ int LevelChunk::countEntities() { #if defined(_ENTITIES_RW_SECTION) LeaveCriticalRWSection(&m_csEntities, false); #else - LeaveCriticalSection(&m_csEntities); + } #endif return entityCount; } @@ -2226,12 +2213,12 @@ void LevelChunk::compressBlocks() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { blocksToCompressLower = lowerBlocks; blocksToCompressUpper = upperBlocks; } - LeaveCriticalSection(&m_csSharing); + } } else { // Not the host, simple case blocksToCompressLower = lowerBlocks; @@ -2325,12 +2312,12 @@ void LevelChunk::compressData() { // Note - only the extraction of the pointers needs to be done in the // critical section, since even if the data is unshared whilst we are // processing this data is still valid (for the server) - EnterCriticalSection(&m_csSharing); + { std::lock_guard lock(m_csSharing); if (sharingTilesAndData) { dataToCompressLower = lowerData; dataToCompressUpper = upperData; } - LeaveCriticalSection(&m_csSharing); + } } else { // Not the host, simple case dataToCompressLower = lowerData; diff --git a/Minecraft.World/Level/LevelChunk.h b/Minecraft.World/Level/LevelChunk.h index 820f1eac8..be32cb0b4 100644 --- a/Minecraft.World/Level/LevelChunk.h +++ b/Minecraft.World/Level/LevelChunk.h @@ -1,5 +1,7 @@ #pragma once +#include + class DataLayer; class TileEntity; class Random; @@ -269,7 +271,7 @@ public: virtual void attemptCompression(); #if defined(SHARING_ENABLED) - static CRITICAL_SECTION m_csSharing; // 4J added + static std::mutex m_csSharing; // 4J added #endif // 4J added #if defined(_ENTITIES_RW_SECTION) @@ -277,9 +279,9 @@ public: m_csEntities; // AP - we're using a RW critical so we can do multiple // reads without contention #else - static CRITICAL_SECTION m_csEntities; + static std::mutex m_csEntities; #endif - static CRITICAL_SECTION m_csTileEntities; // 4J added + static std::mutex m_csTileEntities; // 4J added static void staticCtor(); void checkPostProcess(ChunkSource* source, ChunkSource* parent, int x, int z); diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp index 04f805208..6d9a6a07c 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.cpp +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.cpp @@ -8,7 +8,7 @@ int CompressedTileStorage::deleteQueueIndex; XLockFreeStack CompressedTileStorage::deleteQueue[3]; -CRITICAL_SECTION CompressedTileStorage::cs_write; +std::mutex CompressedTileStorage::cs_write; #if defined(PSVITA_PRECOMPUTED_TABLE) // AP - this will create a precomputed table to speed up getData @@ -35,7 +35,7 @@ CompressedTileStorage::CompressedTileStorage() { } CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { - EnterCriticalSection(&cs_write); + { std::lock_guard lock(cs_write); allocatedSize = copyFrom->allocatedSize; if (allocatedSize > 0) { indicesAndData = (unsigned char*)XPhysicalAlloc( @@ -45,7 +45,7 @@ CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) { } else { indicesAndData = nullptr; } - LeaveCriticalSection(&cs_write); + } #if defined(PSVITA_PRECOMPUTED_TABLE) CompressedTileStorage_InitTable(); @@ -141,9 +141,8 @@ bool CompressedTileStorage::isRenderChunkEmpty( } bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); if (allocatedSize != other->allocatedSize) { - LeaveCriticalSection(&cs_write); return false; } @@ -168,7 +167,6 @@ bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { d0 |= d2; d4 |= d6; if (d0 | d4) { - LeaveCriticalSection(&cs_write); return false; } pOld += 8; @@ -180,12 +178,10 @@ bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) { unsigned char* pucNew = (unsigned char*)pNew; for (int i = 0; i < allocatedSize - (quickCount * 64); i++) { if (*pucOld++ != *pucNew++) { - LeaveCriticalSection(&cs_write); return false; } } - LeaveCriticalSection(&cs_write); return true; } @@ -244,7 +240,7 @@ inline void CompressedTileStorage::getBlock(int* block, int x, int y, int z) { void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { unsigned short _blockIndices[512]; - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); unsigned char* data = dataIn.data + inOffset; // Is the destination fully uncompressed? If so just write our data in - @@ -259,7 +255,6 @@ void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { *dataOut++ = data[getIndex(i, j)]; } } - LeaveCriticalSection(&cs_write); return; } @@ -406,7 +401,6 @@ void CompressedTileStorage::setData(byteArray dataIn, unsigned int inOffset) { } indicesAndData = newIndicesAndData; allocatedSize = memToAlloc; - LeaveCriticalSection(&cs_write); } #if defined(PSVITA_PRECOMPUTED_TABLE) @@ -598,7 +592,7 @@ int CompressedTileStorage::get(int x, int y, int z) { // Set an individual tile value void CompressedTileStorage::set(int x, int y, int z, int val) { - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); assert(val != 255); int block, tile; getBlockAndTile(&block, &tile, x, y, z); @@ -618,7 +612,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { // continue on to upgrade storage if (val == ((blockIndices[block] >> INDEX_TILE_SHIFT) & INDEX_TILE_MASK)) { - LeaveCriticalSection(&cs_write); return; } } else { @@ -627,7 +620,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { data + ((blockIndices[block] >> INDEX_OFFSET_SHIFT) & INDEX_OFFSET_MASK); packed[tile] = val; - LeaveCriticalSection(&cs_write); return; } } else { @@ -660,7 +652,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { int bit = (tile & indexmask_bits) * bitspertile; packed[idx] &= ~(tiletypemask << bit); packed[idx] |= i << bit; - LeaveCriticalSection(&cs_write); return; } } @@ -669,7 +660,6 @@ void CompressedTileStorage::set(int x, int y, int z, int val) { compress(block); } }; - LeaveCriticalSection(&cs_write); } // Sets a region of tile values with the data at offset position in the array @@ -743,7 +733,6 @@ int CompressedTileStorage::getDataRegion(byteArray dataInOut, int x0, int y0, } void CompressedTileStorage::staticCtor() { - InitializeCriticalSectionAndSpinCount(&cs_write, 5120); for (int i = 0; i < 3; i++) { deleteQueue[i].Initialize(); } @@ -793,7 +782,7 @@ void CompressedTileStorage::compress(int upgradeBlock /*=-1*/) { (upgradeBlock > -1); // If an upgrade block is specified, we'll always // need to recompress - otherwise default to false - EnterCriticalSection(&cs_write); + std::lock_guard lock(cs_write); unsigned short* blockIndices = (unsigned short*)indicesAndData; unsigned char* data = indicesAndData + 1024; @@ -1131,7 +1120,6 @@ void CompressedTileStorage::compress(int upgradeBlock /*=-1*/) { indicesAndData = newIndicesAndData; allocatedSize = memToAlloc; } - LeaveCriticalSection(&cs_write); } int CompressedTileStorage::getAllocatedSize(int* count0, int* count1, diff --git a/Minecraft.World/Level/Storage/CompressedTileStorage.h b/Minecraft.World/Level/Storage/CompressedTileStorage.h index 8ef13c61f..5ff5b5b13 100644 --- a/Minecraft.World/Level/Storage/CompressedTileStorage.h +++ b/Minecraft.World/Level/Storage/CompressedTileStorage.h @@ -1,4 +1,5 @@ #pragma once +#include #if !defined(__linux__) #include "../../Platform/x64headers/xmcore.h" #endif @@ -157,7 +158,7 @@ public: static unsigned char compressBuffer[32768 + 256]; - static CRITICAL_SECTION cs_write; + static std::mutex cs_write; int getAllocatedSize(int* count0, int* count1, int* count2, int* count4, int* count8); diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index 041b69782..4717e00f1 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -8,7 +9,7 @@ #include "../LevelData.h" #include "McRegionChunkStorage.h" -CRITICAL_SECTION McRegionChunkStorage::cs_memory; +std::mutex McRegionChunkStorage::cs_memory; std::deque McRegionChunkStorage::s_chunkDataQueue; int McRegionChunkStorage::s_runningThreadCount = 0; @@ -199,14 +200,15 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { PIXEndNamedEvent(); PIXBeginNamedEvent(0, "Updating chunk queue"); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); s_chunkDataQueue.push_back(output); - LeaveCriticalSection(&cs_memory); + } PIXEndNamedEvent(); } else { - EnterCriticalSection(&cs_memory); + CompoundTag* tag; + { std::lock_guard lock(cs_memory); PIXBeginNamedEvent(0, "Creating tags\n"); - CompoundTag* tag = new CompoundTag(); + tag = new CompoundTag(); CompoundTag* levelData = new CompoundTag(); tag->put(L"Level", levelData); OldChunkStorage::save(levelChunk, level, levelData); @@ -214,7 +216,7 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { PIXBeginNamedEvent(0, "NbtIo writing\n"); NbtIo::write(tag, output); PIXEndNamedEvent(); - LeaveCriticalSection(&cs_memory); + } PIXBeginNamedEvent(0, "Output closing\n"); output->close(); PIXEndNamedEvent(); @@ -222,12 +224,12 @@ void McRegionChunkStorage::save(Level* level, LevelChunk* levelChunk) { // 4J Stu - getChunkDataOutputStream makes a new DataOutputStream that // points to a new ChunkBuffer( ByteArrayOutputStream ) We should clean // these up when we are done - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); PIXBeginNamedEvent(0, "Cleaning up\n"); output->deleteChildStream(); delete output; delete tag; - LeaveCriticalSection(&cs_memory); + } PIXEndNamedEvent(); } MemSect(0); @@ -321,8 +323,6 @@ void McRegionChunkStorage::flush() { } void McRegionChunkStorage::staticCtor() { - InitializeCriticalSectionAndSpinCount(&cs_memory, 5120); - for (unsigned int i = 0; i < 3; ++i) { char threadName[256]; sprintf(threadName, "McRegion Save thread %d\n", i); @@ -355,14 +355,15 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { DataOutputStream* dos = nullptr; while (running) { - if (TryEnterCriticalSection(&cs_memory)) { + { std::unique_lock lock(cs_memory, std::try_to_lock); + if (lock.owns_lock()) { lastQueueSize = s_chunkDataQueue.size(); if (lastQueueSize > 0) { dos = s_chunkDataQueue.front(); s_chunkDataQueue.pop_front(); } s_runningThreadCount++; - LeaveCriticalSection(&cs_memory); + lock.unlock(); if (dos) { PIXBeginNamedEvent(0, "Saving chunk"); @@ -375,9 +376,10 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { delete dos; dos = nullptr; - EnterCriticalSection(&cs_memory); + { std::lock_guard lock2(cs_memory); s_runningThreadCount--; - LeaveCriticalSection(&cs_memory); + } + } } // If there was more than one thing in the queue last time we checked, @@ -401,30 +403,32 @@ void McRegionChunkStorage::WaitIfTooManyQueuedChunks() { WaitForSaves(); } // Static void McRegionChunkStorage::WaitForAllSaves() { // Wait for there to be no more tasks to be processed... - EnterCriticalSection(&cs_memory); - size_t queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + size_t queueSize; + { std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); + } while (queueSize > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + } } // And then wait for there to be no running threads that are processing // these tasks - EnterCriticalSection(&cs_memory); - int runningThreadCount = s_runningThreadCount; - LeaveCriticalSection(&cs_memory); + int runningThreadCount; + { std::lock_guard lock(cs_memory); + runningThreadCount = s_runningThreadCount; + } while (runningThreadCount > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); runningThreadCount = s_runningThreadCount; - LeaveCriticalSection(&cs_memory); + } } } @@ -434,17 +438,18 @@ void McRegionChunkStorage::WaitForSaves() { static const int DESIRED_QUEUE_SIZE = 6; // Wait for the queue to reduce to a level where we should add more elements - EnterCriticalSection(&cs_memory); - size_t queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + size_t queueSize; + { std::lock_guard lock(cs_memory); + queueSize = s_chunkDataQueue.size(); + } if (queueSize > MAX_QUEUE_SIZE) { while (queueSize > DESIRED_QUEUE_SIZE) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); - EnterCriticalSection(&cs_memory); + { std::lock_guard lock(cs_memory); queueSize = s_chunkDataQueue.size(); - LeaveCriticalSection(&cs_memory); + } } } } diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.h b/Minecraft.World/Level/Storage/McRegionChunkStorage.h index b82ac6474..f651f95e5 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.h +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "ChunkStorage.h" #include "../LevelChunk.h" #include "RegionFileCache.h" @@ -12,7 +14,7 @@ class McRegionChunkStorage : public ChunkStorage { private: const std::wstring m_prefix; ConsoleSaveFile* m_saveFile; - static CRITICAL_SECTION cs_memory; + static std::mutex cs_memory; std::unordered_map m_entityData; diff --git a/Minecraft.World/Level/Storage/OldChunkStorage.cpp b/Minecraft.World/Level/Storage/OldChunkStorage.cpp index f4b2fa155..5b6f1ae5e 100644 --- a/Minecraft.World/Level/Storage/OldChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/OldChunkStorage.cpp @@ -1,4 +1,5 @@ #include "../../Platform/stdafx.h" +#include #include "../../IO/Files/File.h" #include "../../IO/Streams/InputOutputStream.h" #include "../../Headers/net.minecraft.world.entity.h" @@ -196,29 +197,22 @@ bool OldChunkStorage::saveEntities(LevelChunk* lc, Level* level, lc->lastSaveHadEntities = false; ListTag* entityTags = new ListTag(); -#if defined(_ENTITIES_RW_SECTION) - EnterCriticalRWSection(&lc->m_csEntities, true); -#else - EnterCriticalSection(&lc->m_csEntities); -#endif - for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) { - auto itEnd = lc->entityBlocks[i]->end(); - for (std::vector >::iterator it = - lc->entityBlocks[i]->begin(); - it != itEnd; it++) { - std::shared_ptr e = *it; - lc->lastSaveHadEntities = true; - CompoundTag* teTag = new CompoundTag(); - if (e->save(teTag)) { - entityTags->add(teTag); + { + std::lock_guard lock(lc->m_csEntities); + for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) { + auto itEnd = lc->entityBlocks[i]->end(); + for (std::vector >::iterator it = + lc->entityBlocks[i]->begin(); + it != itEnd; it++) { + std::shared_ptr e = *it; + lc->lastSaveHadEntities = true; + CompoundTag* teTag = new CompoundTag(); + if (e->save(teTag)) { + entityTags->add(teTag); + } } } } -#if defined(_ENTITIES_RW_SECTION) - LeaveCriticalRWSection(&lc->m_csEntities, true); -#else - LeaveCriticalSection(&lc->m_csEntities); -#endif tag->put(L"Entities", entityTags); diff --git a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp index e4b47ff2d..051343e38 100644 --- a/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/ZonedChunkStorage.cpp @@ -1,4 +1,5 @@ #include "../../Platform/stdafx.h" +#include #include "../../IO/Files/File.h" #include "../../IO/Streams/ByteBuffer.h" #include "../../Headers/net.minecraft.world.entity.h" @@ -214,28 +215,21 @@ void ZonedChunkStorage::saveEntities(Level* level, LevelChunk* lc) { std::vector tags; -#ifdef _ENTITIES_RW_SECTION - EnterCriticalRWSection(&lc->m_csEntities, true); -#else - EnterCriticalSection(&lc->m_csEntities); -#endif - for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) { - std::vector >* entities = lc->entityBlocks[i]; + { + std::lock_guard lock(lc->m_csEntities); + for (int i = 0; i < LevelChunk::ENTITY_BLOCKS_LENGTH; i++) { + std::vector >* entities = lc->entityBlocks[i]; - auto itEndTags = entities->end(); - for (auto it = entities->begin(); it != itEndTags; it++) { - std::shared_ptr e = *it; // entities->at(j); - CompoundTag* cp = new CompoundTag(); - cp->putInt(L"_TYPE", 0); - e->save(cp); - tags.push_back(cp); + auto itEndTags = entities->end(); + for (auto it = entities->begin(); it != itEndTags; it++) { + std::shared_ptr e = *it; // entities->at(j); + CompoundTag* cp = new CompoundTag(); + cp->putInt(L"_TYPE", 0); + e->save(cp); + tags.push_back(cp); + } } } -#ifdef _ENTITIES_RW_SECTION - LeaveCriticalRWSection(&lc->m_csEntities, true); -#else - LeaveCriticalSection(&lc->m_csEntities); -#endif for (std::unordered_map, TilePosKeyHash, TilePosKeyEq>::iterator it = diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index cb7ab6c61..e90443f25 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -22,10 +22,6 @@ int Connection::writeSizes[256]; void Connection::_init() { // printf("Con:0x%x init\n",this); - InitializeCriticalSection(&writeLock); - InitializeCriticalSection(&threadCounterLock); - InitializeCriticalSection(&incoming_cs); - running = true; quitting = false; disconnected = false; @@ -54,10 +50,6 @@ Connection::~Connection() { readThread->WaitForCompletion(INFINITE); writeThread->WaitForCompletion(INFINITE); - DeleteCriticalSection(&writeLock); - DeleteCriticalSection(&threadCounterLock); - DeleteCriticalSection(&incoming_cs); - delete m_hWakeReadThread; delete m_hWakeWriteThread; @@ -150,29 +142,31 @@ void Connection::send(std::shared_ptr packet) { MemSect(15); // 4J Jev, synchronized (&writeLock) - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - estimatedRemaining += packet->getEstimatedSize() + 1; - if (packet->shouldDelay) { - // 4J We have delayed it enough by putting it in the slow queue, so - // don't delay when we actually send it - packet->shouldDelay = false; - outgoing_slow.push(packet); - } else { - outgoing.push(packet); + estimatedRemaining += packet->getEstimatedSize() + 1; + if (packet->shouldDelay) { + // 4J We have delayed it enough by putting it in the slow queue, so + // don't delay when we actually send it + packet->shouldDelay = false; + outgoing_slow.push(packet); + } else { + outgoing.push(packet); + } } // 4J Jev, end synchronized. - LeaveCriticalSection(&writeLock); MemSect(0); } void Connection::queueSend(std::shared_ptr packet) { if (quitting) return; - EnterCriticalSection(&writeLock); - estimatedRemaining += packet->getEstimatedSize() + 1; - outgoing_slow.push(packet); - LeaveCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); + estimatedRemaining += packet->getEstimatedSize() + 1; + outgoing_slow.push(packet); + } } bool Connection::writeTick() { @@ -189,13 +183,13 @@ bool Connection::writeTick() { fakeLag)) { std::shared_ptr packet; - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - packet = outgoing.front(); - outgoing.pop(); - estimatedRemaining -= packet->getEstimatedSize() + 1; - - LeaveCriticalSection(&writeLock); + packet = outgoing.front(); + outgoing.pop(); + estimatedRemaining -= packet->getEstimatedSize() + 1; + } Packet::writePacket(packet, bufferedDos); #if defined(__linux__) @@ -238,13 +232,13 @@ bool Connection::writeTick() { // synchronized (writeLock) { - EnterCriticalSection(&writeLock); + { + std::lock_guard lock(writeLock); - packet = outgoing_slow.front(); - outgoing_slow.pop(); - estimatedRemaining -= packet->getEstimatedSize() + 1; - - LeaveCriticalSection(&writeLock); + packet = outgoing_slow.front(); + outgoing_slow.pop(); + estimatedRemaining -= packet->getEstimatedSize() + 1; + } // If the shouldDelay flag is still set at this point then we want to // write it to QNet as a single packet with priority flags Otherwise @@ -329,11 +323,12 @@ bool Connection::readTick() { if (packet != nullptr) { readSizes[packet->getId()] += packet->getEstimatedSize() + 1; - EnterCriticalSection(&incoming_cs); - if (!quitting) { - incoming.push(packet); + { + std::lock_guard lock(incoming_cs); + if (!quitting) { + incoming.push(packet); + } } - LeaveCriticalSection(&incoming_cs); didSomething = true; } else { // printf("Con:0x%x readTick close EOS\n",this); @@ -420,9 +415,11 @@ void Connection::tick() { if (estimatedRemaining > 1 * 1024 * 1024) { close(DisconnectPacket::eDisconnect_Overflow); } - EnterCriticalSection(&incoming_cs); - bool empty = incoming.empty(); - LeaveCriticalSection(&incoming_cs); + bool empty; + { + std::lock_guard lock(incoming_cs); + empty = incoming.empty(); + } if (empty) { #if CONNECTION_ENABLE_TIMEOUT_DISCONNECT if (noInputTicks++ == MAX_TICKS_WITHOUT_INPUT) { @@ -461,16 +458,17 @@ void Connection::tick() { // changed to use a eAppAction_ExitPlayerPreLogin which will run in the main // loop, so the connection will not be ticked at that point - EnterCriticalSection(&incoming_cs); // 4J Stu - If disconnected, then we shouldn't process incoming packets std::vector > packetsToHandle; - while (!disconnected && !g_NetworkManager.IsLeavingGame() && - g_NetworkManager.IsInSession() && !incoming.empty() && max-- >= 0) { - std::shared_ptr packet = incoming.front(); - packetsToHandle.push_back(packet); - incoming.pop(); + { + std::lock_guard lock(incoming_cs); + while (!disconnected && !g_NetworkManager.IsLeavingGame() && + g_NetworkManager.IsInSession() && !incoming.empty() && max-- >= 0) { + std::shared_ptr packet = incoming.front(); + packetsToHandle.push_back(packet); + incoming.pop(); + } } - LeaveCriticalSection(&incoming_cs); // MGH - moved the packet handling outside of the incoming_cs block, as it // was locking up sometimes when disconnecting @@ -492,9 +490,11 @@ void Connection::tick() { // 4J - split the following condition (used to be disconnect && // iscoming.empty()) so we can wrap the access in a critical section if (disconnected) { - EnterCriticalSection(&incoming_cs); - bool empty = incoming.empty(); - LeaveCriticalSection(&incoming_cs); + bool empty; + { + std::lock_guard lock(incoming_cs); + empty = incoming.empty(); + } if (empty) { packetListener->onDisconnect(disconnectReason, disconnectReasonObjects); @@ -540,11 +540,12 @@ int Connection::runRead(void* lpParam) { Compression::UseDefaultThreadStorage(); - CRITICAL_SECTION* cs = &con->threadCounterLock; + std::mutex* cs = &con->threadCounterLock; - EnterCriticalSection(cs); - con->readThreads++; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->readThreads++; + } // try { @@ -587,11 +588,12 @@ int Connection::runWrite(void* lpParam) { Compression::UseDefaultThreadStorage(); - CRITICAL_SECTION* cs = &con->threadCounterLock; + std::mutex* cs = &con->threadCounterLock; - EnterCriticalSection(cs); - con->writeThreads++; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->writeThreads++; + } // 4J Stu - Adding this to force us to run through the writeTick at least // once after the event is fired Otherwise there is a race between the @@ -614,9 +616,10 @@ int Connection::runWrite(void* lpParam) { } // 4J was in a finally block. - EnterCriticalSection(cs); - con->writeThreads--; - LeaveCriticalSection(cs); + { + std::lock_guard lock(*cs); + con->writeThreads--; + } ShutdownManager::HasFinished(ShutdownManager::eConnectionWriteThreads); return 0; diff --git a/Minecraft.World/Network/Connection.h b/Minecraft.World/Network/Connection.h index 2c7cec21e..c9b776b9c 100644 --- a/Minecraft.World/Network/Connection.h +++ b/Minecraft.World/Network/Connection.h @@ -8,6 +8,8 @@ #include "../Headers/net.minecraft.network.packet.h" #include "../Util/C4JThread.h" +#include + #include "Socket.h" // 4J JEV, size of the threads (bytes). @@ -54,7 +56,7 @@ private: std::queue > incoming; // 4J - was using synchronizedList... - CRITICAL_SECTION incoming_cs; // ... now has this critical section + std::mutex incoming_cs; // ... now has this critical section std::queue > outgoing; // 4J - was using synchronizedList - but don't think it is // required as usage is wrapped in writeLock critical section @@ -93,8 +95,8 @@ private: void _init(); // 4J Jev, these might be better of as private - CRITICAL_SECTION threadCounterLock; - CRITICAL_SECTION writeLock; + std::mutex threadCounterLock; + std::mutex writeLock; public: // 4J Jev, need to delete the critical section. diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index 3f8afba37..f0538ca1c 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -14,7 +14,7 @@ // link. 2 sockets can be created, one for either end of this local link, the // end (0 or 1) is passed as a parameter to the ctor. -CRITICAL_SECTION Socket::s_hostQueueLock[2]; +std::mutex Socket::s_hostQueueLock[2]; std::queue Socket::s_hostQueue[2]; Socket::SocketOutputStreamLocal* Socket::s_hostOutStream[2]; Socket::SocketInputStreamLocal* Socket::s_hostInStream[2]; @@ -26,7 +26,6 @@ void Socket::EnsureStreamsInitialised() { // concurrently. static bool initialized = []() -> bool { for (int i = 0; i < 2; i++) { - InitializeCriticalSection(&Socket::s_hostQueueLock[i]); s_hostOutStream[i] = new SocketOutputStreamLocal(i); s_hostInStream[i] = new SocketInputStreamLocal(i); } @@ -47,11 +46,13 @@ void Socket::Initialise(ServerConnection* serverConnection) { if (init) { // Streams already exist – just reset queue state and re-open streams. for (int i = 0; i < 2; i++) { - if (TryEnterCriticalSection(&s_hostQueueLock[i])) { - // Clear the queue - std::queue empty; - std::swap(s_hostQueue[i], empty); - LeaveCriticalSection(&s_hostQueueLock[i]); + { + std::unique_lock lock(s_hostQueueLock[i], std::try_to_lock); + if (lock.owns_lock()) { + // Clear the queue + std::queue empty; + std::swap(s_hostQueue[i], empty); + } } s_hostOutStream[i]->m_streamOpen = true; s_hostInStream[i]->m_streamOpen = true; @@ -94,7 +95,6 @@ Socket::Socket(INetworkPlayer* player, bool response /* = false*/, m_hostLocal = hostLocal; for (int i = 0; i < 2; i++) { - InitializeCriticalSection(&m_queueLockNetwork[i]); m_inputStream[i] = nullptr; m_outputStream[i] = nullptr; m_endClosed[i] = false; @@ -143,11 +143,12 @@ void Socket::pushDataToQueue(const std::uint8_t* pbData, std::size_t dataSize, return; } - EnterCriticalSection(&m_queueLockNetwork[queueIdx]); - for (std::size_t i = 0; i < dataSize; ++i) { - m_queueNetwork[queueIdx].push(*pbData++); + { + std::lock_guard lock(m_queueLockNetwork[queueIdx]); + for (std::size_t i = 0; i < dataSize; ++i) { + m_queueNetwork[queueIdx].push(*pbData++); + } } - LeaveCriticalSection(&m_queueLockNetwork[queueIdx]); } void Socket::addIncomingSocket(Socket* socket) { @@ -244,14 +245,15 @@ Socket::SocketInputStreamLocal::SocketInputStreamLocal(int queueIdx) { int Socket::SocketInputStreamLocal::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { - if (TryEnterCriticalSection(&s_hostQueueLock[m_queueIdx])) { - if (s_hostQueue[m_queueIdx].size()) { - std::uint8_t retval = s_hostQueue[m_queueIdx].front(); - s_hostQueue[m_queueIdx].pop(); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); - return retval; + { + std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (s_hostQueue[m_queueIdx].size()) { + std::uint8_t retval = s_hostQueue[m_queueIdx].front(); + s_hostQueue[m_queueIdx].pop(); + return retval; + } } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -269,16 +271,17 @@ int Socket::SocketInputStreamLocal::read(byteArray b) { int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { - if (TryEnterCriticalSection(&s_hostQueueLock[m_queueIdx])) { - if (s_hostQueue[m_queueIdx].size() >= length) { - for (unsigned int i = 0; i < length; i++) { - b[i + offset] = s_hostQueue[m_queueIdx].front(); - s_hostQueue[m_queueIdx].pop(); + { + std::unique_lock lock(s_hostQueueLock[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (s_hostQueue[m_queueIdx].size() >= length) { + for (unsigned int i = 0; i < length; i++) { + b[i + offset] = s_hostQueue[m_queueIdx].front(); + s_hostQueue[m_queueIdx].pop(); + } + return length; } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); - return length; } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -287,9 +290,10 @@ int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, void Socket::SocketInputStreamLocal::close() { m_streamOpen = false; - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - std::queue().swap(s_hostQueue[m_queueIdx]); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + std::queue().swap(s_hostQueue[m_queueIdx]); + } } /////////////////////////////////// Socket for output, on local connection @@ -304,9 +308,10 @@ void Socket::SocketOutputStreamLocal::write(unsigned int b) { if (m_streamOpen != true) { return; } - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - s_hostQueue[m_queueIdx].push((std::uint8_t)b); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + s_hostQueue[m_queueIdx].push((std::uint8_t)b); + } } void Socket::SocketOutputStreamLocal::write(byteArray b) { @@ -319,19 +324,21 @@ void Socket::SocketOutputStreamLocal::write(byteArray b, unsigned int offset, return; } MemSect(12); - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - for (unsigned int i = 0; i < length; i++) { - s_hostQueue[m_queueIdx].push(b[offset + i]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + for (unsigned int i = 0; i < length; i++) { + s_hostQueue[m_queueIdx].push(b[offset + i]); + } } - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); MemSect(0); } void Socket::SocketOutputStreamLocal::close() { m_streamOpen = false; - EnterCriticalSection(&s_hostQueueLock[m_queueIdx]); - std::queue().swap(s_hostQueue[m_queueIdx]); - LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); + { + std::lock_guard lock(s_hostQueueLock[m_queueIdx]); + std::queue().swap(s_hostQueue[m_queueIdx]); + } } /////////////////////////////////// Socket for input, on network connection @@ -348,16 +355,16 @@ Socket::SocketInputStreamNetwork::SocketInputStreamNetwork(Socket* socket, int Socket::SocketInputStreamNetwork::read() { while (m_streamOpen && ShutdownManager::ShouldRun( ShutdownManager::eConnectionReadThreads)) { - if (TryEnterCriticalSection( - &m_socket->m_queueLockNetwork[m_queueIdx])) { - if (m_socket->m_queueNetwork[m_queueIdx].size()) { - std::uint8_t retval = - m_socket->m_queueNetwork[m_queueIdx].front(); - m_socket->m_queueNetwork[m_queueIdx].pop(); - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); - return retval; + { + std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (m_socket->m_queueNetwork[m_queueIdx].size()) { + std::uint8_t retval = + m_socket->m_queueNetwork[m_queueIdx].front(); + m_socket->m_queueNetwork[m_queueIdx].pop(); + return retval; + } } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -375,18 +382,18 @@ int Socket::SocketInputStreamNetwork::read(byteArray b) { int Socket::SocketInputStreamNetwork::read(byteArray b, unsigned int offset, unsigned int length) { while (m_streamOpen) { - if (TryEnterCriticalSection( - &m_socket->m_queueLockNetwork[m_queueIdx])) { - if (m_socket->m_queueNetwork[m_queueIdx].size() >= length) { - for (unsigned int i = 0; i < length; i++) { - b[i + offset] = - m_socket->m_queueNetwork[m_queueIdx].front(); - m_socket->m_queueNetwork[m_queueIdx].pop(); + { + std::unique_lock lock(m_socket->m_queueLockNetwork[m_queueIdx], std::try_to_lock); + if (lock.owns_lock()) { + if (m_socket->m_queueNetwork[m_queueIdx].size() >= length) { + for (unsigned int i = 0; i < length; i++) { + b[i + offset] = + m_socket->m_queueNetwork[m_queueIdx].front(); + m_socket->m_queueNetwork[m_queueIdx].pop(); + } + return length; } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); - return length; } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -441,11 +448,12 @@ void Socket::SocketOutputStreamNetwork::writeWithFlags(byteArray b, else queueIdx = SOCKET_CLIENT_END; - EnterCriticalSection(&m_socket->m_queueLockNetwork[queueIdx]); - for (unsigned int i = 0; i < length; i++) { - m_socket->m_queueNetwork[queueIdx].push(b[offset + i]); + { + std::lock_guard lock(m_socket->m_queueLockNetwork[queueIdx]); + for (unsigned int i = 0; i < length; i++) { + m_socket->m_queueNetwork[queueIdx].push(b[offset + i]); + } } - LeaveCriticalSection(&m_socket->m_queueLockNetwork[queueIdx]); } else { XRNM_SEND_BUFFER buffer; buffer.pbyData = &b[offset]; diff --git a/Minecraft.World/Network/Socket.h b/Minecraft.World/Network/Socket.h index dd811d940..18719598a 100644 --- a/Minecraft.World/Network/Socket.h +++ b/Minecraft.World/Network/Socket.h @@ -5,6 +5,7 @@ #include #include #endif +#include #include #include "../IO/Streams/InputStream.h" #include "../IO/Streams/OutputStream.h" @@ -107,14 +108,14 @@ private: int m_end; // 0 for client side or 1 for host side // For local connections between the host player and the server - static CRITICAL_SECTION s_hostQueueLock[2]; + static std::mutex s_hostQueueLock[2]; static std::queue s_hostQueue[2]; static SocketOutputStreamLocal* s_hostOutStream[2]; static SocketInputStreamLocal* s_hostInStream[2]; // For network connections std::queue m_queueNetwork[2]; // For input data - CRITICAL_SECTION m_queueLockNetwork[2]; // For input data + std::mutex m_queueLockNetwork[2]; // For input data SocketInputStreamNetwork* m_inputStream[2]; SocketOutputStreamNetwork* m_outputStream[2]; bool m_endClosed[2]; diff --git a/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp b/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp index 44f797141..75fc85b82 100644 --- a/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp +++ b/Minecraft.World/WorldGen/Biomes/BiomeCache.cpp @@ -67,8 +67,6 @@ BiomeCache::BiomeCache(BiomeSource* source) { lastUpdateTime = 0; this->source = source; - - InitializeCriticalSection(&m_CS); } BiomeCache::~BiomeCache() { @@ -78,11 +76,10 @@ BiomeCache::~BiomeCache() { for (auto it = all.begin(); it != all.end(); ++it) { delete (*it); } - DeleteCriticalSection(&m_CS); } BiomeCache::Block* BiomeCache::getBlockAt(int x, int z) { - EnterCriticalSection(&m_CS); + std::lock_guard lock(m_CS); x >>= ZONE_SIZE_BITS; z >>= ZONE_SIZE_BITS; int64_t slot = @@ -99,7 +96,6 @@ BiomeCache::Block* BiomeCache::getBlockAt(int x, int z) { block = it->second; } block->lastUse = app.getAppTime(); - LeaveCriticalSection(&m_CS); return block; } @@ -116,7 +112,7 @@ float BiomeCache::getDownfall(int x, int z) { } void BiomeCache::update() { - EnterCriticalSection(&m_CS); + std::lock_guard lock(m_CS); int64_t now = app.getAppTime(); int64_t utime = now - lastUpdateTime; if (utime > DECAY_TIME / 4 || utime < 0) { @@ -136,7 +132,6 @@ void BiomeCache::update() { } } } - LeaveCriticalSection(&m_CS); } BiomeArray BiomeCache::getBiomeBlockAt(int x, int z) { diff --git a/Minecraft.World/WorldGen/Biomes/BiomeCache.h b/Minecraft.World/WorldGen/Biomes/BiomeCache.h index a5ab51bac..529461404 100644 --- a/Minecraft.World/WorldGen/Biomes/BiomeCache.h +++ b/Minecraft.World/WorldGen/Biomes/BiomeCache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Minecraft.World/Util/JavaIntHash.h" class BiomeCache { @@ -48,5 +49,5 @@ public: byteArray getBiomeIndexBlockAt(int x, int z); private: - CRITICAL_SECTION m_CS; + std::mutex m_CS; }; \ No newline at end of file