Restore recursive locking for mutexes converted from CRITICAL_SECTION

CRITICAL_SECTION is reentrant; std::mutex is not. This caused deadlocks during world generation, post-processing, and saving.
This commit is contained in:
MatthewBeshay 2026-03-30 22:14:14 +11:00
parent 57e4bdd973
commit e4520df31f
19 changed files with 104 additions and 104 deletions

View file

@ -46,7 +46,7 @@ WeighedTreasureArray ServerLevel::RANDOM_BONUS_ITEMS;
C4JThread* ServerLevel::m_updateThread = nullptr;
C4JThread::EventArray* ServerLevel::m_updateTrigger;
std::mutex ServerLevel::m_updateCS[3];
std::recursive_mutex ServerLevel::m_updateCS[3];
Level* ServerLevel::m_level[3];
int ServerLevel::m_updateChunkX[3][LEVEL_CHUNKS_TO_UPDATE_MAX];
@ -184,7 +184,7 @@ ServerLevel::~ServerLevel() {
delete mobSpawner;
{
std::lock_guard<std::mutex> lock(m_csQueueSendTileUpdates);
std::lock_guard<std::recursive_mutex> lock(m_csQueueSendTileUpdates);
for (auto it = m_queuedSendTileUpdates.begin();
it != m_queuedSendTileUpdates.end(); ++it) {
Pos* p = *it;
@ -198,9 +198,9 @@ ServerLevel::~ServerLevel() {
}
// Make sure that the update thread isn't actually doing any updating
{ 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]); }
{ std::lock_guard<std::recursive_mutex> lock(m_updateCS[0]); }
{ std::lock_guard<std::recursive_mutex> lock(m_updateCS[1]); }
{ std::lock_guard<std::recursive_mutex> lock(m_updateCS[2]); }
m_updateTrigger->ClearAll();
}
@ -440,7 +440,7 @@ void ServerLevel::tickTiles() {
unsigned int tickCount = 0;
{
std::lock_guard<std::mutex> lock(m_updateCS[iLev]);
std::lock_guard<std::recursive_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;
@ -594,7 +594,7 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId,
td.setPriorityTilt(priorityTilt);
}
{
std::lock_guard<std::mutex> lock(m_tickNextTickCS);
std::lock_guard<std::recursive_mutex> lock(m_tickNextTickCS);
if (tickNextTickSet.find(td) == tickNextTickSet.end()) {
tickNextTickSet.insert(td);
tickNextTickList.insert(td);
@ -613,7 +613,7 @@ void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId,
td.delay(tickDelay + levelData->getGameTime());
}
{
std::lock_guard<std::mutex> lock(m_tickNextTickCS);
std::lock_guard<std::recursive_mutex> lock(m_tickNextTickCS);
if (tickNextTickSet.find(td) == tickNextTickSet.end()) {
tickNextTickSet.insert(td);
tickNextTickList.insert(td);
@ -636,7 +636,7 @@ void ServerLevel::tickEntities() {
void ServerLevel::resetEmptyTime() { emptyTime = 0; }
bool ServerLevel::tickPendingTicks(bool force) {
std::lock_guard<std::mutex> lock(m_tickNextTickCS);
std::lock_guard<std::recursive_mutex> lock(m_tickNextTickCS);
int count = (int)tickNextTickList.size();
int count2 = (int)tickNextTickSet.size();
if (count != tickNextTickSet.size()) {
@ -685,7 +685,7 @@ bool ServerLevel::tickPendingTicks(bool force) {
std::vector<TickNextTickData>* ServerLevel::fetchTicksInChunk(LevelChunk* chunk,
bool remove) {
std::lock_guard<std::mutex> lock(m_tickNextTickCS);
std::lock_guard<std::recursive_mutex> lock(m_tickNextTickCS);
std::vector<TickNextTickData>* results = new std::vector<TickNextTickData>;
ChunkPos* pos = chunk->getPos();
@ -1215,12 +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) {
std::lock_guard<std::mutex> lock(m_csQueueSendTileUpdates);
std::lock_guard<std::recursive_mutex> lock(m_csQueueSendTileUpdates);
m_queuedSendTileUpdates.push_back(new Pos(x, y, z));
}
void ServerLevel::runQueuedSendTileUpdates() {
std::lock_guard<std::mutex> lock(m_csQueueSendTileUpdates);
std::lock_guard<std::recursive_mutex> lock(m_csQueueSendTileUpdates);
for (auto it = m_queuedSendTileUpdates.begin();
it != m_queuedSendTileUpdates.end(); ++it) {
Pos* p = *it;
@ -1237,7 +1237,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
if (e->instanceof(eTYPE_ITEMENTITY)) {
// printf("Adding item entity count
//%d\n",m_itemEntities.size());
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
if (m_itemEntities.size() >= MAX_ITEM_ENTITIES) {
// printf("Adding - doing remove\n");
removeEntityImmediately(m_itemEntities.front());
@ -1248,7 +1248,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
else if (e->instanceof(eTYPE_HANGING_ENTITY)) {
// printf("Adding item entity count
//%d\n",m_itemEntities.size());
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
if (m_hangingEntities.size() >= MAX_HANGING_ENTITIES) {
// printf("Adding - doing remove\n");
@ -1263,7 +1263,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
else if (e->instanceof(eTYPE_ARROW)) {
// printf("Adding arrow entity count
//%d\n",m_arrowEntities.size());
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
if (m_arrowEntities.size() >= MAX_ARROW_ENTITIES) {
// printf("Adding - doing remove\n");
removeEntityImmediately(m_arrowEntities.front());
@ -1274,7 +1274,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
else if (e->instanceof(eTYPE_EXPERIENCEORB)) {
// printf("Adding arrow entity count
//%d\n",m_arrowEntities.size());
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
if (m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES) {
// printf("Adding - doing remove\n");
removeEntityImmediately(m_experienceOrbEntities.front());
@ -1291,16 +1291,16 @@ bool ServerLevel::atEntityLimit(std::shared_ptr<Entity> e) {
bool atLimit = false;
if (e->instanceof(eTYPE_ITEMENTITY)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
atLimit = m_itemEntities.size() >= MAX_ITEM_ENTITIES;
} else if (e->instanceof(eTYPE_HANGING_ENTITY)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
atLimit = m_hangingEntities.size() >= MAX_HANGING_ENTITIES;
} else if (e->instanceof(eTYPE_ARROW)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
atLimit = m_arrowEntities.size() >= MAX_ARROW_ENTITIES;
} else if (e->instanceof(eTYPE_EXPERIENCEORB)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
atLimit = m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES;
}
@ -1310,30 +1310,30 @@ 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)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_itemEntities.push_back(e);
// printf("entity added: item entity count now
//%d\n",m_itemEntities.size());
} else if (e->instanceof(eTYPE_HANGING_ENTITY)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_hangingEntities.push_back(e);
// printf("entity added: item entity count now
//%d\n",m_itemEntities.size());
} else if (e->instanceof(eTYPE_ARROW)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_arrowEntities.push_back(e);
// printf("entity added: arrow entity count now
//%d\n",m_arrowEntities.size());
} else if (e->instanceof(eTYPE_EXPERIENCEORB)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_experienceOrbEntities.push_back(e);
// printf("entity added: experience orb entity count now
//%d\n",m_arrowEntities.size());
} else if (e->instanceof(eTYPE_PRIMEDTNT)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_primedTntCount++;
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_fallingTileCount++;
}
}
@ -1342,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)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_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);
@ -1353,7 +1353,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: item entity count now
//%d\n",m_itemEntities.size());
} else if (e->instanceof(eTYPE_HANGING_ENTITY)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
// printf("entity removed: item entity count
//%d\n",m_itemEntities.size());
auto it = find(m_hangingEntities.begin(), m_hangingEntities.end(), e);
@ -1364,7 +1364,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: item entity count now
//%d\n",m_itemEntities.size());
} else if (e->instanceof(eTYPE_ARROW)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_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);
@ -1375,7 +1375,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: arrow entity count now
//%d\n",m_arrowEntities.size());
} else if (e->instanceof(eTYPE_EXPERIENCEORB)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
// printf("entity removed: experience orb entity count
//%d\n",m_arrowEntities.size());
auto it = find(m_experienceOrbEntities.begin(),
@ -1387,22 +1387,22 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: experience orb entity count now
//%d\n",m_arrowEntities.size());
} else if (e->instanceof(eTYPE_PRIMEDTNT)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_primedTntCount--;
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
m_fallingTileCount--;
}
}
bool ServerLevel::newPrimedTntAllowed() {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
bool retval = m_primedTntCount < MAX_PRIMED_TNT;
return retval;
}
bool ServerLevel::newFallingTileAllowed() {
std::lock_guard<std::mutex> lock(m_limiterCS);
std::lock_guard<std::recursive_mutex> lock(m_limiterCS);
bool retval = m_fallingTileCount < MAX_FALLING_TILE;
return retval;
}
@ -1422,7 +1422,7 @@ int ServerLevel::runUpdate(void* lpParam) {
int grassTicks = 0;
int lavaTicks = 0;
for (unsigned int iLev = 0; iLev < 3; ++iLev) {
std::lock_guard<std::mutex> lock(m_updateCS[iLev]);
std::lock_guard<std::recursive_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

View file

@ -17,7 +17,7 @@ private:
EntityTracker* tracker;
PlayerChunkMap* chunkMap;
std::mutex m_tickNextTickCS; // 4J added
std::recursive_mutex m_tickNextTickCS; // 4J added
std::set<TickNextTickData, TickNextTickDataKeyCompare>
tickNextTickList; // 4J Was TreeSet
std::unordered_set<TickNextTickData, TickNextTickDataKeyHash,
@ -25,7 +25,7 @@ private:
tickNextTickSet; // 4J Was HashSet
std::vector<Pos*> m_queuedSendTileUpdates; // 4J added
std::mutex m_csQueueSendTileUpdates;
std::recursive_mutex m_csQueueSendTileUpdates;
protected:
int saveInterval;
@ -178,7 +178,7 @@ public:
int m_primedTntCount;
int m_fallingTileCount;
std::mutex m_limiterCS;
std::recursive_mutex m_limiterCS;
std::list<std::shared_ptr<Entity> > m_itemEntities;
std::list<std::shared_ptr<Entity> > m_hangingEntities;
std::list<std::shared_ptr<Entity> > m_arrowEntities;
@ -212,7 +212,7 @@ public:
static int m_randValue[3];
static C4JThread::EventArray* m_updateTrigger;
static std::mutex m_updateCS[3];
static std::recursive_mutex m_updateCS[3];
static C4JThread* m_updateThread;
static int runUpdate(void* lpParam);

View file

@ -987,7 +987,7 @@ void Minecraft::run_middle() {
}
#endif
{ std::lock_guard<std::mutex> lock(m_setLevelCS);
{ std::lock_guard<std::recursive_mutex> lock(m_setLevelCS);
if (running) {
if (reloadTextures) {
@ -3669,7 +3669,7 @@ void Minecraft::setLevel(MultiPlayerLevel* level, int message /*=-1*/,
std::shared_ptr<Player> forceInsertPlayer /*=nullptr*/,
bool doForceStatsSave /*=true*/,
bool bPrimaryPlayerSignedOut /*=false*/) {
std::lock_guard<std::mutex> lock(m_setLevelCS);
std::lock_guard<std::recursive_mutex> lock(m_setLevelCS);
bool playerAdded = false;
this->cameraTargetPlayer = nullptr;

View file

@ -348,7 +348,7 @@ public:
// 4J Stu
void forceStatsSave(int idx);
std::mutex m_setLevelCS;
std::recursive_mutex m_setLevelCS;
private:
// A bit field that store whether a particular quadrant is in the full

View file

@ -144,7 +144,7 @@ LevelChunk* ServerChunkCache::create(
LevelChunk* lastChunk = chunk;
if ((chunk == nullptr) || (chunk->x != x) || (chunk->z != z)) {
{ std::lock_guard<std::mutex> lock(m_csLoadCreate);
{ std::lock_guard<std::recursive_mutex> lock(m_csLoadCreate);
chunk = load(x, z);
if (chunk == nullptr) {
if (source == nullptr) {
@ -169,7 +169,7 @@ LevelChunk* ServerChunkCache::create(
#endif
{
// Successfully updated the cache
std::lock_guard<std::mutex> lock(m_csLoadCreate);
std::lock_guard<std::recursive_mutex> 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
@ -649,7 +649,7 @@ bool ServerChunkCache::saveAllEntities() {
PIXBeginNamedEvent(0, "Save all entities");
PIXBeginNamedEvent(0, "saving to NBT");
{ std::lock_guard<std::mutex> lock(m_csLoadCreate);
{ std::lock_guard<std::recursive_mutex> lock(m_csLoadCreate);
for (auto it = m_loadedChunkList.begin(); it != m_loadedChunkList.end();
++it) {
storage->saveEntities(level, *it);
@ -666,7 +666,7 @@ bool ServerChunkCache::saveAllEntities() {
}
bool ServerChunkCache::save(bool force, ProgressListener* progressListener) {
std::lock_guard<std::mutex> lock(m_csLoadCreate);
std::lock_guard<std::recursive_mutex> lock(m_csLoadCreate);
int saves = 0;
// 4J - added this to support progressListner

View file

@ -31,7 +31,7 @@ private:
#endif
// 4J - added for multithreaded support
std::mutex m_csLoadCreate;
std::recursive_mutex m_csLoadCreate;
// 4J - size of cache is defined by size of one side - must be even
int XZSIZE;
int XZOFFSET;

View file

@ -44,7 +44,7 @@ void UIComponent_Panorama::tick() {
Minecraft* pMinecraft = Minecraft::GetInstance();
{
std::lock_guard<std::mutex> lock(pMinecraft->m_setLevelCS);
std::lock_guard<std::recursive_mutex> 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

View file

@ -151,7 +151,7 @@ void Chunk::setPos(int x, int y, int z) {
assigned = true;
{
std::lock_guard<std::mutex> lock(levelRenderer->m_csDirtyChunks);
std::lock_guard<std::recursive_mutex> 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);
@ -722,7 +722,7 @@ void Chunk::reset() {
bool retireRenderableTileEntities = false;
{
std::lock_guard<std::mutex> lock(levelRenderer->m_csDirtyChunks);
std::lock_guard<std::recursive_mutex> lock(levelRenderer->m_csDirtyChunks);
oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
unsigned char refCount =
levelRenderer->decGlobalChunkRefCount(x, y, z, level);

View file

@ -4,7 +4,7 @@
#include "ProgressRenderer.h"
#include "../../../Minecraft.World/Platform/System.h"
std::mutex ProgressRenderer::s_progress;
std::recursive_mutex ProgressRenderer::s_progress;
ProgressRenderer::ProgressRenderer(Minecraft* minecraft) {
status = -1;
@ -34,7 +34,7 @@ void ProgressRenderer::_progressStart(int title) {
}
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
lastPercent = 0;
this->title = title;
}
@ -48,7 +48,7 @@ void ProgressRenderer::progressStage(int status) {
lastTime = 0;
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
m_eType = eProgressStringType_ID;
this->status = status;
}
@ -60,7 +60,7 @@ void ProgressRenderer::progressStagePercentage(int i) {
// 4J Stu - Removing all progressRenderer rendering. This will be replaced
// on the xbox
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
lastPercent = i;
}
}
@ -68,7 +68,7 @@ void ProgressRenderer::progressStagePercentage(int i) {
int ProgressRenderer::getCurrentPercent() {
int returnValue = 0;
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
returnValue = lastPercent;
}
return returnValue;
@ -77,7 +77,7 @@ int ProgressRenderer::getCurrentPercent() {
int ProgressRenderer::getCurrentTitle() {
int returnValue;
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
returnValue = title;
}
return returnValue;
@ -86,7 +86,7 @@ int ProgressRenderer::getCurrentTitle() {
int ProgressRenderer::getCurrentStatus() {
int returnValue;
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
returnValue = status;
}
return returnValue;
@ -95,25 +95,25 @@ int ProgressRenderer::getCurrentStatus() {
ProgressRenderer::eProgressStringType ProgressRenderer::getType() {
eProgressStringType returnValue;
{
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
returnValue = m_eType;
}
return returnValue;
}
void ProgressRenderer::setType(eProgressStringType eType) {
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
m_eType = eType;
}
void ProgressRenderer::progressStage(std::wstring& wstrText) {
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
m_wstrText = wstrText;
m_eType = eProgressStringType_String;
}
std::wstring& ProgressRenderer::getProgressString(void) {
std::lock_guard<std::mutex> lock(ProgressRenderer::s_progress);
std::lock_guard<std::recursive_mutex> lock(ProgressRenderer::s_progress);
std::wstring& temp = m_wstrText;
return temp;
}

View file

@ -10,7 +10,7 @@ public:
// on a save transfer
};
static std::mutex s_progress;
static std::recursive_mutex s_progress;
int getCurrentPercent();
int getCurrentTitle();

View file

@ -648,7 +648,7 @@ std::wstring LevelRenderer::gatherStats2() {
}
void LevelRenderer::resortChunks(int xc, int yc, int zc) {
std::lock_guard<std::mutex> lock(m_csDirtyChunks);
std::lock_guard<std::recursive_mutex> lock(m_csDirtyChunks);
xc -= CHUNK_XZSIZE / 2;
yc -= CHUNK_SIZE / 2;
zc -= CHUNK_XZSIZE / 2;
@ -1698,7 +1698,7 @@ bool LevelRenderer::updateDirtyChunks() {
ClipChunk* nearChunk = nullptr; // Nearest chunk that is dirty
int veryNearCount = 0;
int minDistSq = 0x7fffffff; // Distances to this chunk
std::unique_lock<std::mutex> dirtyChunksLock(m_csDirtyChunks);
std::unique_lock<std::recursive_mutex> dirtyChunksLock(m_csDirtyChunks);
// Set a flag if we should only rebuild existing chunks, not create anything
// new

View file

@ -216,7 +216,7 @@ private:
public:
void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added
std::mutex m_csDirtyChunks;
std::recursive_mutex m_csDirtyChunks;
bool m_nearDirtyChunk;
// 4J - Destroyed Tile Management - these things added so we can track tiles

View file

@ -24,7 +24,7 @@ private:
#endif
void* pvSaveMem;
std::mutex m_lock;
std::recursive_mutex m_lock;
void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite);
void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite);

View file

@ -80,7 +80,7 @@ private:
#endif
void* pvSaveMem;
std::mutex m_lock;
std::recursive_mutex m_lock;
void PrepareForWrite(FileEntry* file, unsigned int nNumberOfBytesToWrite);
void MoveDataBeyond(FileEntry* file, unsigned int nNumberOfBytesToWrite);

View file

@ -22,16 +22,16 @@
#include <mutex>
#if defined(SHARING_ENABLED)
std::mutex LevelChunk::m_csSharing;
std::recursive_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
std::mutex LevelChunk::m_csEntities;
std::recursive_mutex LevelChunk::m_csEntities;
#endif
std::mutex LevelChunk::m_csTileEntities;
std::recursive_mutex LevelChunk::m_csTileEntities;
bool LevelChunk::touchedSky = false;
void LevelChunk::staticCtor() {
@ -48,7 +48,7 @@ void LevelChunk::init(Level* level, int x, int z) {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
entityBlocks =
new std::vector<std::shared_ptr<Entity> >*[ENTITY_BLOCKS_LENGTH];
@ -79,7 +79,7 @@ void LevelChunk::init(Level* level, int x, int z) {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) {
entityBlocks[i] = new std::vector<std::shared_ptr<Entity> >();
@ -249,7 +249,7 @@ void LevelChunk::setUnsaved(bool unsaved) {
void LevelChunk::stopSharingTilesAndData() {
#if defined(SHARING_ENABLED)
{ std::lock_guard<std::mutex> lock(m_csSharing);
{ std::lock_guard<std::recursive_mutex> lock(m_csSharing);
lastUnsharedTime = System::currentTimeMillis();
if (!sharingTilesAndData) {
return;
@ -315,7 +315,7 @@ void LevelChunk::stopSharingTilesAndData() {
// not sharing
void LevelChunk::reSyncLighting() {
#if defined(SHARING_ENABLED)
{ std::lock_guard<std::mutex> lock(m_csSharing);
{ std::lock_guard<std::recursive_mutex> lock(m_csSharing);
if (isEmpty()) {
return;
@ -352,7 +352,7 @@ void LevelChunk::reSyncLighting() {
void LevelChunk::startSharingTilesAndData(int forceMs) {
#if defined(SHARING_ENABLED)
{ std::lock_guard<std::mutex> lock(m_csSharing);
{ std::lock_guard<std::recursive_mutex> lock(m_csSharing);
if (sharingTilesAndData) {
return;
}
@ -1178,7 +1178,7 @@ void LevelChunk::addEntity(std::shared_ptr<Entity> e) {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
entityBlocks[yc]->push_back(e);
#if defined(_ENTITIES_RW_SECTION)
@ -1199,7 +1199,7 @@ void LevelChunk::removeEntity(std::shared_ptr<Entity> e, int yc) {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
// 4J - was entityBlocks[yc]->remove(e);
@ -1242,7 +1242,7 @@ std::shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z) {
// insert when we don't want one)
// shared_ptr<TileEntity> tileEntity = tileEntities[pos];
std::shared_ptr<TileEntity> tileEntity = nullptr;
{ std::unique_lock<std::mutex> lock(m_csTileEntities);
{ std::unique_lock<std::recursive_mutex> lock(m_csTileEntities);
auto it = tileEntities.find(pos);
if (it == tileEntities.end()) {
@ -1273,7 +1273,7 @@ std::shared_ptr<TileEntity> 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
{ std::lock_guard<std::mutex> lock2(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock2(m_csTileEntities);
auto newIt = tileEntities.find(pos);
if (newIt != tileEntities.end()) {
tileEntity = newIt->second;
@ -1284,7 +1284,7 @@ std::shared_ptr<TileEntity> LevelChunk::getTileEntity(int x, int y, int z) {
}
}
if (tileEntity != nullptr && tileEntity->isRemoved()) {
{ std::lock_guard<std::mutex> lock(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csTileEntities);
tileEntities.erase(pos);
}
return nullptr;
@ -1330,7 +1330,7 @@ void LevelChunk::setTileEntity(int x, int y, int z,
tileEntity->clearRemoved();
{ std::lock_guard<std::mutex> lock(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csTileEntities);
tileEntities[pos] = tileEntity;
}
}
@ -1344,7 +1344,7 @@ void LevelChunk::removeTileEntity(int x, int y, int z) {
// if (removeThis != null) {
// removeThis.setRemoved();
// }
{ std::lock_guard<std::mutex> lock(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csTileEntities);
auto it = tileEntities.find(pos);
if (it != tileEntities.end()) {
std::shared_ptr<TileEntity> te = tileEntities[pos];
@ -1402,7 +1402,7 @@ void LevelChunk::load() {
#endif
std::vector<std::shared_ptr<TileEntity> > values;
{ std::lock_guard<std::mutex> lock(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csTileEntities);
for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) {
values.push_back(it->second);
}
@ -1412,7 +1412,7 @@ void LevelChunk::load() {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) {
level->addEntities(entityBlocks[i]);
@ -1434,7 +1434,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter
loaded = false;
if (unloadTileEntities) {
std::vector<std::shared_ptr<TileEntity> > tileEntitiesToRemove;
{ std::lock_guard<std::mutex> lock(m_csTileEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csTileEntities);
for (auto it = tileEntities.begin(); it != tileEntities.end(); it++) {
tileEntitiesToRemove.push_back(it->second);
}
@ -1450,7 +1450,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) {
level->removeEntities(entityBlocks[i]);
@ -1475,7 +1475,7 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter
PIXBeginNamedEvent(0, "Saving entities");
ListTag<CompoundTag>* entityTags = new ListTag<CompoundTag>();
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) {
auto itEnd = entityBlocks[i]->end();
for (std::vector<std::shared_ptr<Entity> >::iterator it =
@ -1523,7 +1523,7 @@ bool LevelChunk::containsPlayer() {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, true);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
for (int i = 0; i < ENTITY_BLOCKS_LENGTH; i++) {
std::vector<std::shared_ptr<Entity> >* vecEntity = entityBlocks[i];
@ -1561,7 +1561,7 @@ void LevelChunk::getEntities(std::shared_ptr<Entity> except, AABB* bb,
// AP - RW critical sections are expensive so enter once in
// Level::getEntities
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
for (int yc = yc0; yc <= yc1; yc++) {
std::vector<std::shared_ptr<Entity> >* entities = entityBlocks[yc];
@ -1607,7 +1607,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb,
// AP - RW critical sections are expensive so enter once in
// Level::getEntitiesOfClass
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
for (int yc = yc0; yc <= yc1; yc++) {
std::vector<std::shared_ptr<Entity> >* entities = entityBlocks[yc];
@ -1655,7 +1655,7 @@ int LevelChunk::countEntities() {
#if defined(_ENTITIES_RW_SECTION)
EnterCriticalRWSection(&m_csEntities, false);
#else
{ std::lock_guard<std::mutex> lock(m_csEntities);
{ std::lock_guard<std::recursive_mutex> lock(m_csEntities);
#endif
for (int yc = 0; yc < ENTITY_BLOCKS_LENGTH; yc++) {
entityCount += (int)entityBlocks[yc]->size();
@ -2208,7 +2208,7 @@ 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)
{ std::lock_guard<std::mutex> lock(m_csSharing);
{ std::lock_guard<std::recursive_mutex> lock(m_csSharing);
if (sharingTilesAndData) {
blocksToCompressLower = lowerBlocks;
blocksToCompressUpper = upperBlocks;
@ -2307,7 +2307,7 @@ 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)
{ std::lock_guard<std::mutex> lock(m_csSharing);
{ std::lock_guard<std::recursive_mutex> lock(m_csSharing);
if (sharingTilesAndData) {
dataToCompressLower = lowerData;
dataToCompressUpper = upperData;

View file

@ -270,7 +270,7 @@ public:
virtual void attemptCompression();
#if defined(SHARING_ENABLED)
static std::mutex m_csSharing; // 4J added
static std::recursive_mutex m_csSharing; // 4J added
#endif
// 4J added
#if defined(_ENTITIES_RW_SECTION)
@ -278,9 +278,9 @@ public:
m_csEntities; // AP - we're using a RW critical so we can do multiple
// reads without contention
#else
static std::mutex m_csEntities;
static std::recursive_mutex m_csEntities;
#endif
static std::mutex m_csTileEntities; // 4J added
static std::recursive_mutex m_csTileEntities; // 4J added
static void staticCtor();
void checkPostProcess(ChunkSource* source, ChunkSource* parent, int x,
int z);

View file

@ -6,7 +6,7 @@
int CompressedTileStorage::deleteQueueIndex;
XLockFreeStack<unsigned char> CompressedTileStorage::deleteQueue[3];
std::mutex CompressedTileStorage::cs_write;
std::recursive_mutex CompressedTileStorage::cs_write;
#if defined(PSVITA_PRECOMPUTED_TABLE)
// AP - this will create a precomputed table to speed up getData
@ -33,7 +33,7 @@ CompressedTileStorage::CompressedTileStorage() {
}
CompressedTileStorage::CompressedTileStorage(CompressedTileStorage* copyFrom) {
{ std::lock_guard<std::mutex> lock(cs_write);
{ std::lock_guard<std::recursive_mutex> lock(cs_write);
allocatedSize = copyFrom->allocatedSize;
if (allocatedSize > 0) {
indicesAndData = (unsigned char*)XPhysicalAlloc(
@ -139,7 +139,7 @@ bool CompressedTileStorage::isRenderChunkEmpty(
}
bool CompressedTileStorage::isSameAs(CompressedTileStorage* other) {
std::lock_guard<std::mutex> lock(cs_write);
std::lock_guard<std::recursive_mutex> lock(cs_write);
if (allocatedSize != other->allocatedSize) {
return false;
}
@ -238,7 +238,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];
std::lock_guard<std::mutex> lock(cs_write);
std::lock_guard<std::recursive_mutex> lock(cs_write);
unsigned char* data = dataIn.data + inOffset;
// Is the destination fully uncompressed? If so just write our data in -
@ -590,7 +590,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) {
std::lock_guard<std::mutex> lock(cs_write);
std::lock_guard<std::recursive_mutex> lock(cs_write);
assert(val != 255);
int block, tile;
getBlockAndTile(&block, &tile, x, y, z);
@ -778,7 +778,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
std::lock_guard<std::mutex> lock(cs_write);
std::lock_guard<std::recursive_mutex> lock(cs_write);
unsigned short* blockIndices = (unsigned short*)indicesAndData;
unsigned char* data = indicesAndData + 1024;

View file

@ -158,7 +158,7 @@ public:
static unsigned char compressBuffer[32768 + 256];
static std::mutex cs_write;
static std::recursive_mutex cs_write;
int getAllocatedSize(int* count0, int* count1, int* count2, int* count4,
int* count8);

View file

@ -198,7 +198,7 @@ bool OldChunkStorage::saveEntities(LevelChunk* lc, Level* level,
ListTag<CompoundTag>* entityTags = new ListTag<CompoundTag>();
{
std::lock_guard<std::mutex> lock(lc->m_csEntities);
std::lock_guard<std::recursive_mutex> lock(lc->m_csEntities);
for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++) {
auto itEnd = lc->entityBlocks[i]->end();
for (std::vector<std::shared_ptr<Entity> >::iterator it =