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.
This commit is contained in:
MatthewBeshay
2026-03-30 18:45:55 +11:00
parent c772cfe8b3
commit bc6013ab70
59 changed files with 952 additions and 1128 deletions

View File

@@ -1,5 +1,6 @@
#include <thread>
#include <chrono>
#include <mutex>
#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<std::mutex> 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<std::mutex> lock(m_updateCS[0]); }
{ std::lock_guard<std::mutex> lock(m_updateCS[1]); }
{ std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<TickNextTickData>* ServerLevel::fetchTicksInChunk(LevelChunk* chunk,
bool remove) {
EnterCriticalSection(&m_tickNextTickCS);
std::lock_guard<std::mutex> lock(m_tickNextTickCS);
std::vector<TickNextTickData>* results = new std::vector<TickNextTickData>;
ChunkPos* pos = chunk->getPos();
@@ -749,7 +740,6 @@ std::vector<TickNextTickData>* 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<std::mutex> lock(m_csQueueSendTileUpdates);
m_queuedSendTileUpdates.push_back(new Pos(x, y, z));
LeaveCriticalSection(&m_csQueueSendTileUpdates);
}
void ServerLevel::runQueuedSendTileUpdates() {
EnterCriticalSection(&m_csQueueSendTileUpdates);
std::lock_guard<std::mutex> 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<Entity> e) {
if (e->instanceof(eTYPE_ITEMENTITY)) {
// printf("Adding item entity count
//%d\n",m_itemEntities.size());
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<Entity> e) {
bool atLimit = false;
if (e->instanceof(eTYPE_ITEMENTITY)) {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<Entity> e) {
// Maintain a cound of primed tnt & falling tiles in this level
void ServerLevel::entityAddedExtra(std::shared_ptr<Entity> e) {
if (e->instanceof(eTYPE_ITEMENTITY)) {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(m_limiterCS);
m_primedTntCount++;
LeaveCriticalSection(&m_limiterCS);
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> lock(m_limiterCS);
m_fallingTileCount++;
LeaveCriticalSection(&m_limiterCS);
}
}
@@ -1369,7 +1342,7 @@ void ServerLevel::entityAddedExtra(std::shared_ptr<Entity> e) {
// item entities from our list
void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
if (e->instanceof(eTYPE_ITEMENTITY)) {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> 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<Entity> 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<std::mutex> 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<Entity> 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<std::mutex> 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<Entity> 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<std::mutex> 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<Entity> 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<std::mutex> lock(m_limiterCS);
m_primedTntCount--;
LeaveCriticalSection(&m_limiterCS);
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> lock(m_limiterCS);
m_fallingTileCount--;
LeaveCriticalSection(&m_limiterCS);
}
}
bool ServerLevel::newPrimedTntAllowed() {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> lock(m_limiterCS);
bool retval = m_primedTntCount < MAX_PRIMED_TNT;
LeaveCriticalSection(&m_limiterCS);
return retval;
}
bool ServerLevel::newFallingTileAllowed() {
EnterCriticalSection(&m_limiterCS);
std::lock_guard<std::mutex> 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<std::mutex> 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();
}