diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp index 2686f7a5a..afd3315ad 100644 --- a/Minecraft.Client/Level/ServerLevel.cpp +++ b/Minecraft.Client/Level/ServerLevel.cpp @@ -62,8 +62,8 @@ void ServerLevel::staticCtor() { m_updateTrigger = new C4JThread::EventArray(3); m_updateThread = new C4JThread(runUpdate, nullptr, "Tile update"); - m_updateThread->SetProcessor(CPU_CORE_TILE_UPDATE); - m_updateThread->Run(); + m_updateThread->setProcessor(CPU_CORE_TILE_UPDATE); + m_updateThread->run(); RANDOM_BONUS_ITEMS = WeighedTreasureArray(20); @@ -201,7 +201,7 @@ ServerLevel::~ServerLevel() { { std::lock_guard lock(m_updateCS[0]); } { std::lock_guard lock(m_updateCS[1]); } { std::lock_guard lock(m_updateCS[2]); } - m_updateTrigger->ClearAll(); + m_updateTrigger->clearAll(); } void ServerLevel::tick() { @@ -553,7 +553,7 @@ void ServerLevel::tickTiles() { m_level[iLev] = this; m_randValue[iLev] = randValue; // We've set up everything that the udpate thread needs, so kick it off - m_updateTrigger->Set(iLev); + m_updateTrigger->set(iLev); } bool ServerLevel::isTileToBeTickedAt(int x, int y, int z, int tileId) { @@ -1411,7 +1411,7 @@ int ServerLevel::runUpdate(void* lpParam) { ShutdownManager::HasStarted(ShutdownManager::eRunUpdateThread, m_updateTrigger); while (ShutdownManager::ShouldRun(ShutdownManager::eRunUpdateThread)) { - m_updateTrigger->WaitForAll(INFINITE); + m_updateTrigger->waitForAll(C4JThread::kInfiniteTimeout); if (!ShutdownManager::ShouldRun(ShutdownManager::eRunUpdateThread)) break; diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index faf44a939..de9428a74 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -212,7 +212,7 @@ Minecraft::Minecraft(Component* mouseComponent, Canvas* parent, new C4JThread::EventQueue(levelTickUpdateFunc, levelTickThreadInitFunc, "LevelTick_EventQueuePoll"); levelTickEventQueue->setProcessor(3); - levelTickEventQueue->setPriority(THREAD_PRIORITY_NORMAL); + levelTickEventQueue->setPriority(C4JThread::ThreadPriority::Normal); #endif } diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index c914a5d80..c5fb9936a 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -303,8 +303,8 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { } do { - status = m_postUpdateThread->WaitForCompletion(50); - if (status == WAIT_TIMEOUT) { + status = m_postUpdateThread->waitForCompletion(50); + if (status == C4JThread::WaitResult::Timeout) { { std::lock_guard lock(server->m_postProcessCS); postProcessItemRemaining = server->m_postProcessRequests.size(); @@ -319,7 +319,7 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer* mcprogress) { SparseLightStorage::tick(); SparseDataStorage::tick(); } - } while (status == WAIT_TIMEOUT); + } while (status == C4JThread::WaitResult::Timeout); delete m_postUpdateThread; m_postUpdateThread = nullptr; } @@ -493,9 +493,9 @@ bool MinecraftServer::loadLevel(LevelStorageSource* storageSource, new C4JThread(runPostUpdate, this, "Post processing", 256 * 1024); m_postUpdateTerminate = false; - m_postUpdateThread->SetProcessor(CPU_CORE_POST_PROCESSING); - m_postUpdateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); - m_postUpdateThread->Run(); + m_postUpdateThread->setProcessor(CPU_CORE_POST_PROCESSING); + m_postUpdateThread->setPriority(C4JThread::ThreadPriority::AboveNormal); + m_postUpdateThread->run(); int64_t startTime = System::currentTimeMillis(); @@ -1244,7 +1244,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) { case eXuiServerAction_PauseServer: m_isServerPaused = ((size_t)param == true); if (m_isServerPaused) { - m_serverPausedEvent->Set(); + m_serverPausedEvent->set(); } break; case eXuiServerAction_ToggleRain: { diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp index 566fea724..40628a484 100644 --- a/Minecraft.Client/Network/ServerChunkCache.cpp +++ b/Minecraft.Client/Network/ServerChunkCache.cpp @@ -859,8 +859,8 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { } // Wait for the producer thread to tell us to start - params->wakeEvent->WaitForSignal( - INFINITE); // WaitForSingleObject(params->wakeEvent,INFINITE); + params->wakeEvent->waitForSignal( + C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); // app.DebugPrintf("Save thread has started\n"); @@ -880,14 +880,14 @@ int ServerChunkCache::runSaveThreadProc(void* lpParam) { // Inform the producer thread that we are done with this chunk params->notificationEvent - ->Set(); // SetEvent(params->notificationEvent); + ->set(); // SetEvent(params->notificationEvent); // app.DebugPrintf("Save thread has alerted producer that it is // complete\n"); // Wait for the producer thread to tell us to go again - params->wakeEvent->WaitForSignal( - INFINITE); // WaitForSingleObject(params->wakeEvent,INFINITE); + params->wakeEvent->waitForSignal( + C4JThread::kInfiniteTimeout); // WaitForSingleObject(params->wakeEvent,INFINITE); PIXEndNamedEvent(); } diff --git a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp index 12376e5c1..29e246508 100644 --- a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp +++ b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp @@ -462,7 +462,7 @@ void SoundEngine::playMusicTick() { SetIsPlayingStreamingCDMusic(isCD); m_openStreamThread = new C4JThread( OpenStreamThreadProc, this, "OpenStreamThreadProc"); - m_openStreamThread->Run(); + m_openStreamThread->run(); m_StreamState = eMusicStreamState_Opening; } else { app.DebugPrintf( @@ -1493,7 +1493,7 @@ void SoundEngine::playMusicUpdate() { // ~300ms. m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc"); - m_openStreamThread->Run(); + m_openStreamThread->run(); m_StreamState = eMusicStreamState_Opening; } break; diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp index 5d9411d51..600a3e3f3 100644 --- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp +++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp @@ -640,9 +640,9 @@ bool SonyLeaderboardManager::OpenSession() { if (m_threadScoreboard == nullptr) { m_threadScoreboard = new C4JThread(&scoreboardThreadEntry, this, "4JScoreboard"); - m_threadScoreboard->SetProcessor(CPU_CORE_LEADERBOARDS); - m_threadScoreboard->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); - m_threadScoreboard->Run(); + m_threadScoreboard->setProcessor(CPU_CORE_LEADERBOARDS); + m_threadScoreboard->setPriority(C4JThread::ThreadPriority::BelowNormal); + m_threadScoreboard->run(); } app.DebugPrintf( diff --git a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp index feb99fb17..ab700d242 100644 --- a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp @@ -213,8 +213,8 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft, new C4JThread(&CGameNetworkManager::ServerThreadProc, lpParameter, "Server", 256 * 1024); - thread->SetProcessor(CPU_CORE_SERVER); - thread->Run(); + thread->setProcessor(CPU_CORE_SERVER); + thread->run(); app.DebugPrintf("[NET] Waiting for server ready...\n"); ServerReadyWait(); @@ -916,7 +916,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) { eXuiServerAction_PauseServer, (void*)true); // wait for the server to be in a non-ticking state - pServer->m_serverPausedEvent->WaitForSignal(INFINITE); + pServer->m_serverPausedEvent->waitForSignal(C4JThread::kInfiniteTimeout); pMinecraft->progressRenderer->progressStartNoAbort( g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT)); @@ -1495,7 +1495,7 @@ void CGameNetworkManager::ServerReadyCreate(bool create) { void CGameNetworkManager::ServerReady() { if (m_hServerReadyEvent != nullptr) { - m_hServerReadyEvent->Set(); + m_hServerReadyEvent->set(); } else { app.DebugPrintf( "[NET] Warning: ServerReady() called but m_hServerReadyEvent is " @@ -1505,7 +1505,7 @@ void CGameNetworkManager::ServerReady() { void CGameNetworkManager::ServerReadyWait() { if (m_hServerReadyEvent != nullptr) { - m_hServerReadyEvent->WaitForSignal(INFINITE); + m_hServerReadyEvent->waitForSignal(C4JThread::kInfiniteTimeout); } else { app.DebugPrintf( "[NET] Warning: ServerReadyWait() called but m_hServerReadyEvent " @@ -1528,7 +1528,7 @@ void CGameNetworkManager::ServerStoppedCreate(bool create) { void CGameNetworkManager::ServerStopped() { if (m_hServerStoppedEvent != nullptr) { - m_hServerStoppedEvent->Set(); + m_hServerStoppedEvent->set(); } else { app.DebugPrintf( "[NET] Warning: ServerStopped() called but m_hServerStoppedEvent " @@ -1543,10 +1543,10 @@ void CGameNetworkManager::ServerStoppedWait() { // it might be locked waiting for this to complete itself. Do some ticking // here then if this is the case. if (C4JThread::isMainThread()) { - int result = WAIT_TIMEOUT; + int result = C4JThread::WaitResult::Timeout; do { RenderManager.StartFrame(); - result = m_hServerStoppedEvent->WaitForSignal(20); + result = m_hServerStoppedEvent->waitForSignal(20); // Tick some simple things ProfileManager.Tick(); StorageManager.Tick(); @@ -1555,10 +1555,10 @@ void CGameNetworkManager::ServerStoppedWait() { ui.tick(); ui.render(); RenderManager.Present(); - } while (result == WAIT_TIMEOUT); + } while (result == C4JThread::WaitResult::Timeout); } else { if (m_hServerStoppedEvent != nullptr) { - m_hServerStoppedEvent->WaitForSignal(INFINITE); + m_hServerStoppedEvent->waitForSignal(C4JThread::kInfiniteTimeout); } else { app.DebugPrintf( "[NET] Warning: ServerStoppedWait() called but " diff --git a/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp index 446d7a81e..9bc82654a 100644 --- a/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Platform/Common/Network/PlatformNetworkManagerStub.cpp @@ -330,7 +330,7 @@ int CPlatformNetworkManagerStub::RemovePlayerOnSocketClosedThreadProc( if (socket != nullptr) { // printf("Waiting for socket closed event\n"); - socket->m_socketClosedEvent->WaitForSignal(INFINITE); + socket->m_socketClosedEvent->waitForSignal(C4JThread::kInfiniteTimeout); // printf("Socket closed event has fired\n"); // 4J Stu - Clear our reference to this socket diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp index f5a80b595..dcff5c66f 100644 --- a/Minecraft.Client/Platform/Common/UI/UIController.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp @@ -588,13 +588,13 @@ void UIController::ReloadSkin() { m_reloadSkinThread = new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread"); - m_reloadSkinThread->SetProcessor(CPU_CORE_UI_SCENE); + m_reloadSkinThread->setProcessor(CPU_CORE_UI_SCENE); // Navigate to the timer scene so that we can display something while the // loading is happening ui.NavigateToScene(0, eUIScene_Timer, (void*)1, eUILayer_Tooltips, eUIGroup_Fullscreen); - // m_reloadSkinThread->Run(); + // m_reloadSkinThread->run(); //// Load new skin // loadSkins(); @@ -611,7 +611,7 @@ void UIController::ReloadSkin() { } void UIController::StartReloadSkinThread() { - if (m_reloadSkinThread) m_reloadSkinThread->Run(); + if (m_reloadSkinThread) m_reloadSkinThread->run(); } int UIController::reloadSkinThreadProc(void* lpParam) { diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp index edb108e6c..b03c1b7d5 100644 --- a/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp +++ b/Minecraft.Client/Platform/Common/UI/UIScene_FullscreenProgress.cpp @@ -63,11 +63,11 @@ UIScene_FullscreenProgress::UIScene_FullscreenProgress(int iPad, void* initData, m_labelTip.setVisible(m_CompletionData->bShowTips); thread = new C4JThread(params->func, params->lpParam, "FullscreenProgress"); - thread->SetProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is + thread->setProcessor(CPU_CORE_UI_SCENE); // TODO 4J Stu - Make sure this is // a good thread/core to use m_threadCompleted = false; - thread->Run(); + thread->run(); threadStarted = true; } @@ -92,12 +92,12 @@ void UIScene_FullscreenProgress::updateTooltips() { } void UIScene_FullscreenProgress::handleDestroy() { - int code = thread->GetExitCode(); + int code = thread->getExitCode(); const unsigned int exitcode = static_cast(code); // If we're active, have a cancel func, and haven't already cancelled, call // cancel func - if (exitcode == STILL_ACTIVE && m_cancelFunc != nullptr && + if (exitcode == C4JThread::kStillActive && m_cancelFunc != nullptr && !m_bWasCancelled) { m_bWasCancelled = true; m_cancelFunc(m_cancelFuncParam); @@ -140,12 +140,12 @@ void UIScene_FullscreenProgress::tick() { m_progressBar.setLabel(wstrText.c_str()); } - int code = thread->GetExitCode(); + int code = thread->getExitCode(); uint32_t exitcode = *((uint32_t*)&code); // app.DebugPrintf("CScene_FullscreenProgress Timer %d\n",pTimer->nId); - if (exitcode != STILL_ACTIVE) { + if (exitcode != C4JThread::kStillActive) { // If we failed (currently used by network connection thread), navigate // back if (exitcode != S_OK) { diff --git a/Minecraft.Client/Platform/Linux/Linux_App.cpp b/Minecraft.Client/Platform/Linux/Linux_App.cpp index 6e519a20a..e7d5d629a 100644 --- a/Minecraft.Client/Platform/Linux/Linux_App.cpp +++ b/Minecraft.Client/Platform/Linux/Linux_App.cpp @@ -115,7 +115,7 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart() { C4JThread* thread = new C4JThread(loadingParams->func, loadingParams->lpParam, "RunNetworkGame"); - thread->Run(); + thread->run(); } int CConsoleMinecraftApp::GetLocalTMSFileIndex(wchar_t* wchTMSFile, diff --git a/Minecraft.Client/Platform/Windows64/Windows64_App.cpp b/Minecraft.Client/Platform/Windows64/Windows64_App.cpp index 8bccd39a6..c9371b695 100644 --- a/Minecraft.Client/Platform/Windows64/Windows64_App.cpp +++ b/Minecraft.Client/Platform/Windows64/Windows64_App.cpp @@ -108,7 +108,7 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart() { C4JThread* thread = new C4JThread(loadingParams->func, loadingParams->lpParam, "RunNetworkGame"); - thread->Run(); + thread->run(); } int CConsoleMinecraftApp::GetLocalTMSFileIndex(wchar_t* wchTMSFile, diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp index e590c9167..b74a05259 100644 --- a/Minecraft.Client/Rendering/GameRenderer.cpp +++ b/Minecraft.Client/Rendering/GameRenderer.cpp @@ -167,12 +167,12 @@ GameRenderer::GameRenderer(Minecraft* mc) { #if defined(MULTITHREAD_ENABLE) m_updateEvents = new C4JThread::EventArray( - eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); - m_updateEvents->Set(eUpdateEventIsFinished); + eUpdateEventCount, C4JThread::EventArray::Mode::AutoClear); + m_updateEvents->set(eUpdateEventIsFinished); m_updateThread = new C4JThread(runUpdate, nullptr, "Chunk update"); - m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); - m_updateThread->Run(); + m_updateThread->setProcessor(CPU_CORE_CHUNK_UPDATE); + m_updateThread->run(); #endif } @@ -1080,17 +1080,17 @@ int GameRenderer::runUpdate(void* lpParam) { m_updateEvents); while ( ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread)) { - // m_updateEvents->Clear(eUpdateEventIsFinished); - // m_updateEvents->WaitForSingle(eUpdateCanRun,INFINITE); + // m_updateEvents->clear(eUpdateEventIsFinished); + // m_updateEvents->waitForSingle(eUpdateCanRun,C4JThread::kInfiniteTimeout); // 4J Stu - We Need to have this happen atomically to avoid deadlocks - m_updateEvents->WaitForAll(INFINITE); + m_updateEvents->waitForAll(C4JThread::kInfiniteTimeout); if (!ShutdownManager::ShouldRun( ShutdownManager::eRenderChunkUpdateThread)) { break; } - m_updateEvents->Set(eUpdateCanRun); + m_updateEvents->set(eUpdateCanRun); // PIXBeginNamedEvent(0,"Updating dirty chunks //%d",(count++)&7); @@ -1143,7 +1143,7 @@ int GameRenderer::runUpdate(void* lpParam) { // PIXEndNamedEvent(); - m_updateEvents->Set(eUpdateEventIsFinished); + m_updateEvents->set(eUpdateEventIsFinished); } ShutdownManager::HasFinished(ShutdownManager::eRenderChunkUpdateThread); @@ -1160,8 +1160,8 @@ void GameRenderer::EnableUpdateThread() { app.DebugPrintf( "------------------EnableUpdateThread--------------------\n"); updateRunning = true; - m_updateEvents->Set(eUpdateCanRun); - m_updateEvents->Set(eUpdateEventIsFinished); + m_updateEvents->set(eUpdateCanRun); + m_updateEvents->set(eUpdateEventIsFinished); #endif } @@ -1174,8 +1174,8 @@ void GameRenderer::DisableUpdateThread() { app.DebugPrintf( "------------------DisableUpdateThread--------------------\n"); updateRunning = false; - m_updateEvents->Clear(eUpdateCanRun); - m_updateEvents->WaitForSingle(eUpdateEventIsFinished, INFINITE); + m_updateEvents->clear(eUpdateCanRun); + m_updateEvents->waitForSingle(eUpdateEventIsFinished, C4JThread::kInfiniteTimeout); #endif } diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp index bc52e1de6..434f1134e 100644 --- a/Minecraft.Client/Rendering/LevelRenderer.cpp +++ b/Minecraft.Client/Rendering/LevelRenderer.cpp @@ -1945,7 +1945,7 @@ bool LevelRenderer::updateDirtyChunks() { for (int i = MAX_CHUNK_REBUILD_THREADS - 1; i >= 0; --i) { // Set the events that won't run if ((i + 1) > index) - s_rebuildCompleteEvents->Set(i); + s_rebuildCompleteEvents->set(i); else break; } @@ -1974,7 +1974,7 @@ bool LevelRenderer::updateDirtyChunks() { if (index != 0) { FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_rebuildCompleteEvents->Set( + s_rebuildCompleteEvents->set( index - 1); // MGH - this rebuild happening on the main // thread instead, mark the thread it // should have been running on as complete @@ -1990,14 +1990,14 @@ bool LevelRenderer::updateDirtyChunks() { else { // Activate thread to rebuild this chunk FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_activationEventA[index - 1]->Set(); + s_activationEventA[index - 1]->set(); } } // Wait for the other threads to be done as well { FRAME_PROFILE_SCOPE(ChunkRebuildSchedule); - s_rebuildCompleteEvents->WaitForAll(INFINITE); + s_rebuildCompleteEvents->waitForAll(C4JThread::kInfiniteTimeout); } } #else @@ -4005,14 +4005,14 @@ void LevelRenderer::staticCtor() { // Threads 1,3 and 5 are generally idle so use them if ((i % 3) == 0) - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_A); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_A); else if ((i % 3) == 1) { - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_B); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_B); } else if ((i % 3) == 2) - rebuildThreads[i]->SetProcessor(CPU_CORE_CHUNK_REBUILD_C); + rebuildThreads[i]->setProcessor(CPU_CORE_CHUNK_REBUILD_C); // ResumeThread( saveThreads[j] ); - rebuildThreads[i]->Run(); + rebuildThreads[i]->run(); } } @@ -4025,7 +4025,7 @@ int LevelRenderer::rebuildChunkThreadProc(void* lpParam) { int index = (int)(uintptr_t)lpParam; while (true) { - s_activationEventA[index]->WaitForSignal(INFINITE); + s_activationEventA[index]->waitForSignal(C4JThread::kInfiniteTimeout); // app.DebugPrintf("Rebuilding permaChunk %d\n", index + 1); { @@ -4034,7 +4034,7 @@ int LevelRenderer::rebuildChunkThreadProc(void* lpParam) { } // Inform the producer thread that we are done with this chunk - s_rebuildCompleteEvents->Set(index); + s_rebuildCompleteEvents->set(index); } return 0; diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index d880d410a..bba7b774a 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -336,14 +336,14 @@ void McRegionChunkStorage::staticCtor() { // Threads 1,3 and 5 are generally idle so use them if (i == 0) - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_A); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_A); else if (i == 1) { - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_B); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_B); } else if (i == 2) - s_saveThreads[i]->SetProcessor(CPU_CORE_SAVE_THREAD_C); + s_saveThreads[i]->setProcessor(CPU_CORE_SAVE_THREAD_C); // ResumeThread( saveThreads[j] ); - s_saveThreads[i]->Run(); + s_saveThreads[i]->run(); } } diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index 83651a18e..6b5849d20 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -46,8 +46,8 @@ Connection::~Connection() { dis->close(); // The input stream needs closed before the readThread, // or the readThread may get stuck whilst blocking // waiting on a read - readThread->WaitForCompletion(INFINITE); - writeThread->WaitForCompletion(INFINITE); + readThread->waitForCompletion(C4JThread::kInfiniteTimeout); + writeThread->waitForCompletion(C4JThread::kInfiniteTimeout); delete m_hWakeReadThread; delete m_hWakeWriteThread; @@ -111,11 +111,11 @@ Connection::Connection(Socket* socket, const std::wstring& id, new C4JThread(runRead, (void*)this, readThreadName, READ_STACK_SIZE); writeThread = new C4JThread(runWrite, this, writeThreadName, WRITE_STACK_SIZE); - readThread->SetProcessor(CPU_CORE_CONNECTIONS); - writeThread->SetProcessor(CPU_CORE_CONNECTIONS); + readThread->setProcessor(CPU_CORE_CONNECTIONS); + writeThread->setProcessor(CPU_CORE_CONNECTIONS); - readThread->Run(); - writeThread->Run(); + readThread->run(); + writeThread->run(); /* 4J JEV, java: new Thread(wstring(id).append(L" read thread")) { @@ -304,8 +304,8 @@ void Connection::flush() { // multithreaded functions a bit more // readThread.interrupt(); // writeThread.interrupt(); - m_hWakeReadThread->Set(); - m_hWakeWriteThread->Set(); + m_hWakeReadThread->set(); + m_hWakeWriteThread->set(); } bool Connection::readTick() { @@ -388,8 +388,8 @@ void Connection::close(DisconnectPacket::eDisconnectReason reason) { // Make sure that the read & write threads are dead before we go and kill // the streams that they depend on - readThread->WaitForCompletion(INFINITE); - writeThread->WaitForCompletion(INFINITE); + readThread->waitForCompletion(C4JThread::kInfiniteTimeout); + writeThread->waitForCompletion(C4JThread::kInfiniteTimeout); delete dis; dis = nullptr; @@ -558,7 +558,7 @@ int Connection::runRead(void* lpParam) { // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well - con->m_hWakeReadThread->WaitForSignal(100L); + con->m_hWakeReadThread->waitForSignal(100L); } MemSect(0); @@ -598,17 +598,17 @@ int Connection::runWrite(void* lpParam) { // once after the event is fired Otherwise there is a race between the // calling thread setting the running flag and this loop checking the // condition - unsigned int waitResult = WAIT_TIMEOUT; + unsigned int waitResult = C4JThread::WaitResult::Timeout; while ( - (con->running || waitResult == WAIT_OBJECT_0) && + (con->running || waitResult == C4JThread::WaitResult::Signaled) && ShutdownManager::ShouldRun(ShutdownManager::eConnectionWriteThreads)) { while (con->writeTick()); // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well - waitResult = con->m_hWakeWriteThread->WaitForSignal(100L); + waitResult = con->m_hWakeWriteThread->waitForSignal(100L); if (con->bufferedDos != nullptr) con->bufferedDos->flush(); // if (con->byteArrayDos != nullptr) con->byteArrayDos->flush(); diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index 1ce1df879..c0d16bd82 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -227,7 +227,7 @@ bool Socket::close(bool isServerConnection) { m_endClosed[m_end] = true; } if (allClosed && m_socketClosedEvent != nullptr) { - m_socketClosedEvent->Set(); + m_socketClosedEvent->set(); } if (allClosed) createdOk = false; return allClosed; diff --git a/Minecraft.World/Util/C4JThread.cpp b/Minecraft.World/Util/C4JThread.cpp index 209eb7e29..f3ba46fc8 100644 --- a/Minecraft.World/Util/C4JThread.cpp +++ b/Minecraft.World/Util/C4JThread.cpp @@ -2,17 +2,15 @@ #include "C4JThread.h" -#include #include #include #include #include #include #include -#include -#include #include #include +#include #include #if defined(_WIN32) @@ -30,145 +28,109 @@ #include "../../Minecraft.Client/Platform/Common/ShutdownManager.h" -#if !defined(INFINITE) -#define INFINITE 0xFFFFFFFFu -#endif - -#if !defined(WAIT_OBJECT_0) -#define WAIT_OBJECT_0 0u -#endif - -#if !defined(WAIT_TIMEOUT) -#define WAIT_TIMEOUT 258u -#endif - -#if !defined(STILL_ACTIVE) -#define STILL_ACTIVE 259 -#endif - -#if !defined(THREAD_PRIORITY_IDLE) -#define THREAD_PRIORITY_IDLE (-15) -#endif - -#if !defined(THREAD_PRIORITY_LOWEST) -#define THREAD_PRIORITY_LOWEST (-2) -#endif - -#if !defined(THREAD_PRIORITY_BELOW_NORMAL) -#define THREAD_PRIORITY_BELOW_NORMAL (-1) -#endif - -#if !defined(THREAD_PRIORITY_NORMAL) -#define THREAD_PRIORITY_NORMAL 0 -#endif - -#if !defined(THREAD_PRIORITY_ABOVE_NORMAL) -#define THREAD_PRIORITY_ABOVE_NORMAL 1 -#endif - -#if !defined(THREAD_PRIORITY_HIGHEST) -#define THREAD_PRIORITY_HIGHEST 2 -#endif - -#if !defined(THREAD_PRIORITY_TIME_CRITICAL) -#define THREAD_PRIORITY_TIME_CRITICAL 15 -#endif - thread_local C4JThread* C4JThread::ms_currentThread = nullptr; namespace { constexpr int kDefaultStackSize = 65536 * 2; constexpr int kMinimumStackSize = 16384; -constexpr int kUnsetPriority = std::numeric_limits::min(); +constexpr auto kUnsetPriority = + static_cast(std::numeric_limits::min()); constexpr int kEventQueueShutdownPollMs = 100; const std::thread::id g_processMainThreadId = std::this_thread::get_id(); template -bool WaitForCondition(std::condition_variable& condition, +bool waitForCondition(std::condition_variable& condition, std::unique_lock& lock, int timeoutMs, Predicate predicate) { - if (timeoutMs < 0 || static_cast(timeoutMs) == - static_cast(INFINITE)) { + if (timeoutMs < 0) { condition.wait(lock, predicate); return true; } - return condition.wait_for(lock, std::chrono::milliseconds(timeoutMs), predicate); } -std::uint32_t FirstSetBitIndex(std::uint32_t bitMask) { +std::uint32_t firstSetBitIndex(std::uint32_t bitMask) { return static_cast(std::countr_zero(bitMask)); } -std::uint32_t BuildMaskForSize(int size) { - assert(size > 0); - assert(size <= 32); - - if (size == 32) { - return 0xFFFFFFFFU; - } - +std::uint32_t buildMaskForSize(int size) { + assert(size > 0 && size <= 32); + if (size == 32) return 0xFFFFFFFFU; return (1U << static_cast(size)) - 1U; } -void FormatThreadName(std::string& outThreadName, const char* threadName) { - const char* safeName = (threadName != nullptr && threadName[0] != '\0') - ? threadName - : "Unnamed"; - - char buffer[64]; - std::snprintf(buffer, sizeof(buffer), "(4J) %s", safeName); - buffer[sizeof(buffer) - 1] = '\0'; - outThreadName = buffer; +void formatThreadName(std::string& out, const char* name) { + const char* safe = (name && name[0] != '\0') ? name : "Unnamed"; + char buf[64]; + std::snprintf(buf, sizeof(buf), "(4J) %s", safe); + out = buf; } -const char* GetSafeThreadName(const char* threadName) { - return (threadName != nullptr && threadName[0] != '\0') ? threadName - : "(4J) Unnamed"; -} - -bool IsProcessorIndexPlausible(int proc) { - if (proc < 0) { - return true; - } - - const unsigned int hardwareThreads = std::thread::hardware_concurrency(); - if (hardwareThreads == 0U) { - return true; - } - - return static_cast(proc) < hardwareThreads; +bool isProcessorIndexPlausible(int proc) { + if (proc < 0) return true; + const unsigned hw = std::thread::hardware_concurrency(); + return hw == 0U || static_cast(proc) < hw; } +std::int64_t getNativeThreadId() { #if defined(__linux__) -std::int64_t GetLinuxThreadId() { return static_cast(::syscall(SYS_gettid)); +#else + return 0; +#endif } -int MapPriorityToNice(int priority) { - switch (priority) { - case THREAD_PRIORITY_TIME_CRITICAL: - return -15; - case THREAD_PRIORITY_HIGHEST: - return -10; - case THREAD_PRIORITY_ABOVE_NORMAL: - return -5; - case THREAD_PRIORITY_NORMAL: - return 0; - case THREAD_PRIORITY_BELOW_NORMAL: - return 5; - case THREAD_PRIORITY_LOWEST: - return 10; - case THREAD_PRIORITY_IDLE: - return 19; - default: - return 0; +void setThreadNamePlatform([[maybe_unused]] std::uint32_t threadId, + [[maybe_unused]] const char* name) { +#if defined(_WIN32) + // Try modern API first (Windows 10 1607+). + if (threadId == static_cast(-1) || + threadId == ::GetCurrentThreadId()) { + using SetThreadDescriptionFn = int32_t(WINAPI*)(void*, PCWSTR); + const HMODULE kernel = ::GetModuleHandleW(L"Kernel32.dll"); + if (kernel) { + const auto fn = reinterpret_cast( + ::GetProcAddress(kernel, "SetThreadDescription")); + if (fn) { + wchar_t wide[64]; + const auto n = std::mbstowcs( + wide, name, (sizeof(wide) / sizeof(wide[0])) - 1); + if (n != static_cast(-1)) { + wide[n] = L'\0'; + (void)fn(::GetCurrentThread(), wide); + return; + } + } + } } -} + + // Legacy fallback: raise exception 0x406D1388 for older MSVC debuggers. +#pragma pack(push, 8) + struct THREADNAME_INFO { + std::uint32_t dwType; + const char* szName; + std::uint32_t dwThreadID; + std::uint32_t dwFlags; + }; +#pragma pack(pop) + + THREADNAME_INFO info{0x1000, name, threadId, 0}; + __try { + ::RaiseException(0x406D1388, 0, sizeof(info) / sizeof(uintptr_t), + reinterpret_cast(&info)); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } + +#elif defined(__linux__) + // pthread_setname_np limit: 16 chars including null terminator. + char truncated[16]; + std::snprintf(truncated, sizeof(truncated), "%s", name); + (void)::pthread_setname_np(::pthread_self(), truncated); #endif +} #if defined(_WIN32) thread_local std::vector g_affinityMaskStack; @@ -176,28 +138,126 @@ thread_local std::vector g_affinityMaskStack; thread_local std::vector g_affinityMaskStack; #endif +void setAffinityPlatform(std::thread& threadHandle, bool isSelf, int proc) { +#if defined(_WIN32) + void* handle = nullptr; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::GetCurrentThread(); + else + return; + + DWORD_PTR mask = 0; + if (proc < 0) { + DWORD_PTR processMask = 0, systemMask = 0; + if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask, + &systemMask) || + processMask == 0) + return; + mask = processMask; + } else { + constexpr auto bitCount = + static_cast(sizeof(DWORD_PTR) * CHAR_BIT); + if (static_cast(proc) >= bitCount) return; + mask = static_cast(1) << static_cast(proc); + } + (void)::SetThreadAffinityMask(handle, mask); + +#elif defined(__linux__) + pthread_t handle; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::pthread_self(); + else + return; + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if (proc < 0) { + if (::sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) return; + } else { + if (proc >= CPU_SETSIZE) return; + CPU_SET(proc, &cpuset); + } + (void)::pthread_setaffinity_np(handle, sizeof(cpuset), &cpuset); +#else + (void)threadHandle; + (void)isSelf; + (void)proc; +#endif +} + +void setPriorityPlatform(std::thread& threadHandle, bool isSelf, + C4JThread::ThreadPriority priority, + std::atomic& nativeTid) { +#if defined(_WIN32) + void* handle = nullptr; + if (threadHandle.joinable()) + handle = threadHandle.native_handle(); + else if (isSelf) + handle = ::GetCurrentThread(); + else + return; + (void)::SetThreadPriority(handle, std::to_underlying(priority)); + +#elif defined(__linux__) + std::int64_t tid = 0; + if (isSelf) { + tid = getNativeThreadId(); + nativeTid.store(tid, std::memory_order_release); + } else { + tid = nativeTid.load(std::memory_order_acquire); + } + if (tid <= 0) return; + + using enum C4JThread::ThreadPriority; + int niceValue = 0; + switch (priority) { + case TimeCritical: niceValue = -15; break; + case Highest: niceValue = -10; break; + case AboveNormal: niceValue = -5; break; + case Normal: niceValue = 0; break; + case BelowNormal: niceValue = 5; break; + case Lowest: niceValue = 10; break; + case Idle: niceValue = 19; break; + default: niceValue = 0; break; + } + + errno = 0; + if (::setpriority(PRIO_PROCESS, static_cast(tid), niceValue) != 0) { + if ((errno == EACCES || errno == EPERM) && niceValue < 0) { + (void)::setpriority(PRIO_PROCESS, static_cast(tid), 0); + } + } +#else + (void)threadHandle; + (void)isSelf; + (void)priority; + (void)nativeTid; +#endif +} + } // namespace C4JThread::C4JThread(C4JThreadStartFunc* startFunc, void* param, const char* threadName, int stackSize) : m_threadParam(param), m_startFunc(startFunc), - m_stackSize(stackSize == 0 ? kDefaultStackSize : stackSize), + m_stackSize(std::max(stackSize == 0 ? kDefaultStackSize : stackSize, + kMinimumStackSize)), m_threadName(), m_isRunning(false), m_hasStarted(false), - m_exitCode(STILL_ACTIVE), + m_exitCode(kStillActive), m_threadID(), m_threadHandle(), - m_completionFlag(std::make_unique(Event::e_modeManualClear)), + m_completionFlag(std::make_unique(Event::Mode::ManualClear)), m_requestedProcessor(-1), m_requestedPriority(kUnsetPriority), m_nativeTid(0) { - if (m_stackSize < kMinimumStackSize) { - m_stackSize = kMinimumStackSize; - } - - FormatThreadName(m_threadName, threadName); + formatThreadName(m_threadName, threadName); } C4JThread::C4JThread(const char* mainThreadName) @@ -207,21 +267,16 @@ C4JThread::C4JThread(const char* mainThreadName) m_threadName(), m_isRunning(true), m_hasStarted(true), - m_exitCode(STILL_ACTIVE), + m_exitCode(kStillActive), m_threadID(std::this_thread::get_id()), m_threadHandle(), - m_completionFlag(std::make_unique(Event::e_modeManualClear)), + m_completionFlag(std::make_unique(Event::Mode::ManualClear)), m_requestedProcessor(-1), m_requestedPriority(kUnsetPriority), -#if defined(__linux__) - m_nativeTid(GetLinuxThreadId()) -#else - m_nativeTid(0) -#endif -{ - FormatThreadName(m_threadName, mainThreadName); + m_nativeTid(getNativeThreadId()) { + formatThreadName(m_threadName, mainThreadName); ms_currentThread = this; - SetCurrentThreadName(m_threadName.c_str()); + setCurrentThreadName(m_threadName.c_str()); } C4JThread::~C4JThread() { @@ -246,28 +301,25 @@ C4JThread& C4JThread::getMainThreadInstance() noexcept { void C4JThread::entryPoint(C4JThread* pThread) { ms_currentThread = pThread; pThread->m_threadID = std::this_thread::get_id(); + pThread->m_nativeTid.store(getNativeThreadId(), std::memory_order_release); -#if defined(__linux__) - pThread->m_nativeTid.store(GetLinuxThreadId(), std::memory_order_release); -#endif - - SetCurrentThreadName(pThread->m_threadName.c_str()); + setCurrentThreadName(pThread->m_threadName.c_str()); const int requestedProcessor = pThread->m_requestedProcessor.load(std::memory_order_acquire); if (requestedProcessor >= 0) { - pThread->SetProcessor(requestedProcessor); + pThread->setProcessor(requestedProcessor); } - const int requestedPriority = + const auto requestedPriority = pThread->m_requestedPriority.load(std::memory_order_acquire); if (requestedPriority != kUnsetPriority) { - pThread->SetPriority(requestedPriority); + pThread->setPriority(requestedPriority); } int exitCode = 0; try { - exitCode = (pThread->m_startFunc != nullptr) + exitCode = pThread->m_startFunc ? (*pThread->m_startFunc)(pThread->m_threadParam) : 0; } catch (...) { @@ -276,10 +328,10 @@ void C4JThread::entryPoint(C4JThread* pThread) { pThread->m_exitCode.store(exitCode, std::memory_order_release); pThread->m_isRunning.store(false, std::memory_order_release); - pThread->m_completionFlag->Set(); + pThread->m_completionFlag->set(); } -void C4JThread::Run() { +void C4JThread::run() { bool expected = false; if (!m_hasStarted.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) { @@ -287,8 +339,8 @@ void C4JThread::Run() { } m_isRunning.store(true, std::memory_order_release); - m_exitCode.store(STILL_ACTIVE, std::memory_order_release); - m_completionFlag->Clear(); + m_exitCode.store(kStillActive, std::memory_order_release); + m_completionFlag->clear(); m_nativeTid.store(0, std::memory_order_release); m_threadHandle = std::thread(&C4JThread::entryPoint, this); @@ -297,169 +349,50 @@ void C4JThread::Run() { const int requestedProcessor = m_requestedProcessor.load(std::memory_order_acquire); if (requestedProcessor >= 0) { - SetProcessor(requestedProcessor); + setProcessor(requestedProcessor); } - const int requestedPriority = + const auto requestedPriority = m_requestedPriority.load(std::memory_order_acquire); if (requestedPriority != kUnsetPriority) { - SetPriority(requestedPriority); + setPriority(requestedPriority); } } -void C4JThread::SetProcessor(int proc) { +void C4JThread::setProcessor(int proc) { m_requestedProcessor.store(proc, std::memory_order_release); - - if (!IsProcessorIndexPlausible(proc)) { - return; - } - -#if defined(_WIN32) - void* threadHandle = nullptr; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::GetCurrentThread(); - } else { - return; - } - - DWORD_PTR affinityMask = 0; - if (proc < 0) { - DWORD_PTR processAffinityMask = 0; - DWORD_PTR systemAffinityMask = 0; - if (!::GetProcessAffinityMask(::GetCurrentProcess(), - &processAffinityMask, - &systemAffinityMask) || - processAffinityMask == 0) { - return; - } - affinityMask = processAffinityMask; - } else { - const unsigned int bitCount = - static_cast(sizeof(DWORD_PTR) * CHAR_BIT); - if (static_cast(proc) >= bitCount) { - return; - } - - affinityMask = - (static_cast(1) << static_cast(proc)); - } - - (void)::SetThreadAffinityMask(threadHandle, affinityMask); - -#elif defined(__linux__) - pthread_t threadHandle; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::pthread_self(); - } else { - return; - } - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - - if (proc < 0) { - if (::sched_getaffinity(0, sizeof(cpuset), &cpuset) != 0) { - return; - } - } else { - if (proc >= CPU_SETSIZE) { - return; - } - CPU_SET(proc, &cpuset); - } - - (void)::pthread_setaffinity_np(threadHandle, sizeof(cpuset), &cpuset); -#else - (void)proc; -#endif + if (!isProcessorIndexPlausible(proc)) return; + setAffinityPlatform(m_threadHandle, ms_currentThread == this, proc); } -void C4JThread::SetPriority(int priority) { +void C4JThread::setPriority(ThreadPriority priority) { m_requestedPriority.store(priority, std::memory_order_release); - -#if defined(_WIN32) - void* threadHandle = nullptr; - - if (m_threadHandle.joinable()) { - threadHandle = m_threadHandle.native_handle(); - } else if (ms_currentThread == this) { - threadHandle = ::GetCurrentThread(); - } else { - return; - } - - (void)::SetThreadPriority(threadHandle, priority); - -#elif defined(__linux__) - std::int64_t nativeTid = 0; - - if (ms_currentThread == this) { - nativeTid = GetLinuxThreadId(); - m_nativeTid.store(nativeTid, std::memory_order_release); - } else { - nativeTid = m_nativeTid.load(std::memory_order_acquire); - } - - if (nativeTid <= 0) { - return; - } - - const int niceValue = MapPriorityToNice(priority); - - errno = 0; - if (::setpriority(PRIO_PROCESS, static_cast(nativeTid), niceValue) != - 0) { - if ((errno == EACCES || errno == EPERM) && niceValue < 0) { - (void)::setpriority(PRIO_PROCESS, static_cast(nativeTid), 0); - } - } -#else - (void)priority; -#endif + setPriorityPlatform(m_threadHandle, ms_currentThread == this, priority, + m_nativeTid); } -std::uint32_t C4JThread::WaitForCompletion(int timeoutMs) { - const std::uint32_t waitResult = m_completionFlag->WaitForSignal(timeoutMs); - if (waitResult == WAIT_OBJECT_0 && m_threadHandle.joinable()) { +std::uint32_t C4JThread::waitForCompletion(int timeoutMs) { + const std::uint32_t result = m_completionFlag->waitForSignal(timeoutMs); + if (result == WaitResult::Signaled && m_threadHandle.joinable()) { if (m_threadHandle.get_id() == std::this_thread::get_id()) { m_threadHandle.detach(); } else { m_threadHandle.join(); } } - return waitResult; + return result; } -int C4JThread::GetExitCode() const noexcept { +int C4JThread::getExitCode() const noexcept { return m_isRunning.load(std::memory_order_acquire) - ? STILL_ACTIVE + ? kStillActive : m_exitCode.load(std::memory_order_acquire); } -void C4JThread::Sleep(int millisecs) { - if (millisecs <= 0) { - std::this_thread::yield(); - return; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(millisecs)); -} - C4JThread* C4JThread::getCurrentThread() noexcept { - if (ms_currentThread != nullptr) { - return ms_currentThread; - } - - if (std::this_thread::get_id() == g_processMainThreadId) { + if (ms_currentThread) return ms_currentThread; + if (std::this_thread::get_id() == g_processMainThreadId) return &getMainThreadInstance(); - } - return nullptr; } @@ -467,213 +400,122 @@ bool C4JThread::isMainThread() noexcept { return std::this_thread::get_id() == g_processMainThreadId; } -void C4JThread::SetThreadName(std::uint32_t threadId, const char* threadName) { - const char* safeThreadName = GetSafeThreadName(threadName); - -#if defined(_WIN32) - if (threadId == static_cast(-1) || - threadId == ::GetCurrentThreadId()) { - using SetThreadDescriptionFn = int32_t(WINAPI*)(void*, PCWSTR); - - const HMODULE kernelModule = ::GetModuleHandleW(L"Kernel32.dll"); - if (kernelModule != nullptr) { - const auto setThreadDescription = - reinterpret_cast( - ::GetProcAddress(kernelModule, "SetThreadDescription")); - - if (setThreadDescription != nullptr) { - wchar_t wideName[64]; - const std::size_t converted = - std::mbstowcs(wideName, safeThreadName, - (sizeof(wideName) / sizeof(wideName[0])) - 1); - - if (converted != static_cast(-1)) { - wideName[converted] = L'\0'; - (void)setThreadDescription(::GetCurrentThread(), wideName); - return; - } - } - } - } - -#pragma pack(push, 8) - struct THREADNAME_INFO { - std::uint32_t dwType; - const char* szName; - std::uint32_t dwThreadID; - std::uint32_t dwFlags; - }; -#pragma pack(pop) - - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = safeThreadName; - info.dwThreadID = threadId; - info.dwFlags = 0; - - __try { - ::RaiseException(0x406D1388, 0, sizeof(info) / sizeof(uintptr_t), - reinterpret_cast(&info)); - } __except (EXCEPTION_EXECUTE_HANDLER) { - } - -#elif defined(__linux__) - (void)threadId; - - char truncatedName[16]; - std::snprintf(truncatedName, sizeof(truncatedName), "%s", safeThreadName); - truncatedName[sizeof(truncatedName) - 1] = '\0'; - - (void)::pthread_setname_np(::pthread_self(), truncatedName); - -#else - (void)threadId; - (void)safeThreadName; -#endif +void C4JThread::setThreadName(std::uint32_t threadId, const char* threadName) { + const char* safe = (threadName && threadName[0] != '\0') ? threadName + : "(4J) Unnamed"; + setThreadNamePlatform(threadId, safe); } -void C4JThread::SetCurrentThreadName(const char* threadName) { - SetThreadName(static_cast(-1), threadName); +void C4JThread::setCurrentThreadName(const char* threadName) { + setThreadName(static_cast(-1), threadName); } -C4JThread::Event::Event(EMode mode) +C4JThread::Event::Event(Mode mode) : m_mode(mode), m_mutex(), m_condition(), m_signaled(false) {} -void C4JThread::Event::Set() { +void C4JThread::Event::set() { { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_signaled = true; } - - if (m_mode == e_modeAutoClear) { + if (m_mode == Mode::AutoClear) m_condition.notify_one(); - } else { + else m_condition.notify_all(); - } } -void C4JThread::Event::Clear() { - std::lock_guard lock(m_mutex); +void C4JThread::Event::clear() { + std::lock_guard lock(m_mutex); m_signaled = false; } -std::uint32_t C4JThread::Event::WaitForSignal(int timeoutMs) { - std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition(m_condition, lock, timeoutMs, - [this] { return m_signaled; }); - - if (!signaled) { - return WAIT_TIMEOUT; +std::uint32_t C4JThread::Event::waitForSignal(int timeoutMs) { + std::unique_lock lock(m_mutex); + if (!waitForCondition(m_condition, lock, timeoutMs, + [this] { return m_signaled; })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaled = false; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaled = false; + return WaitResult::Signaled; } -C4JThread::EventArray::EventArray(int size, EMode mode) +C4JThread::EventArray::EventArray(int size, Mode mode) : m_size(size), m_mode(mode), m_mutex(), m_condition(), m_signaledMask(0U) { - assert(m_size > 0); - assert(m_size <= 32); + assert(m_size > 0 && m_size <= 32); } -void C4JThread::EventArray::Set(int index) { - assert(index >= 0); - assert(index < m_size); - +void C4JThread::EventArray::set(int index) { + assert(index >= 0 && index < m_size); { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_signaledMask |= (1U << static_cast(index)); } - m_condition.notify_all(); } -void C4JThread::EventArray::Clear(int index) { - assert(index >= 0); - assert(index < m_size); - - std::lock_guard lock(m_mutex); +void C4JThread::EventArray::clear(int index) { + assert(index >= 0 && index < m_size); + std::lock_guard lock(m_mutex); m_signaledMask &= ~(1U << static_cast(index)); } -void C4JThread::EventArray::SetAll() { +void C4JThread::EventArray::setAll() { { - std::lock_guard lock(m_mutex); - m_signaledMask |= BuildMaskForSize(m_size); + std::lock_guard lock(m_mutex); + m_signaledMask |= buildMaskForSize(m_size); } - m_condition.notify_all(); } -void C4JThread::EventArray::ClearAll() { - std::lock_guard lock(m_mutex); +void C4JThread::EventArray::clearAll() { + std::lock_guard lock(m_mutex); m_signaledMask = 0U; } -std::uint32_t C4JThread::EventArray::WaitForSingle(int index, int timeoutMs) { - assert(index >= 0); - assert(index < m_size); - +std::uint32_t C4JThread::EventArray::waitForSingle(int index, int timeoutMs) { + assert(index >= 0 && index < m_size); const std::uint32_t bitMask = 1U << static_cast(index); - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) != 0U; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~bitMask; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; + return WaitResult::Signaled; } -std::uint32_t C4JThread::EventArray::WaitForAll(int timeoutMs) { - const std::uint32_t bitMask = BuildMaskForSize(m_size); - std::unique_lock lock(m_mutex); +std::uint32_t C4JThread::EventArray::waitForAll(int timeoutMs) { + const std::uint32_t bitMask = buildMaskForSize(m_size); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) == bitMask; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) == bitMask; + })) { + return WaitResult::Timeout; } - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~bitMask; - } - - return WAIT_OBJECT_0; + if (m_mode == Mode::AutoClear) m_signaledMask &= ~bitMask; + return WaitResult::Signaled; } -std::uint32_t C4JThread::EventArray::WaitForAny(int timeoutMs) { - const std::uint32_t bitMask = BuildMaskForSize(m_size); - std::unique_lock lock(m_mutex); +std::uint32_t C4JThread::EventArray::waitForAny(int timeoutMs) { + const std::uint32_t bitMask = buildMaskForSize(m_size); + std::unique_lock lock(m_mutex); - const bool signaled = WaitForCondition( - m_condition, lock, timeoutMs, - [this, bitMask] { return (m_signaledMask & bitMask) != 0U; }); - - if (!signaled) { - return WAIT_TIMEOUT; + if (!waitForCondition(m_condition, lock, timeoutMs, + [this, bitMask] { + return (m_signaledMask & bitMask) != 0U; + })) { + return WaitResult::Timeout; } - const std::uint32_t readyMask = m_signaledMask & bitMask; - const std::uint32_t readyIndex = FirstSetBitIndex(readyMask); - - if (m_mode == e_modeAutoClear) { - m_signaledMask &= ~(1U << readyIndex); - } - - return WAIT_OBJECT_0 + readyIndex; + const std::uint32_t readyIndex = + firstSetBitIndex(m_signaledMask & bitMask); + if (m_mode == Mode::AutoClear) m_signaledMask &= ~(1U << readyIndex); + return WaitResult::Signaled + readyIndex; } C4JThread::EventQueue::EventQueue(UpdateFunc* updateFunc, @@ -686,88 +528,67 @@ C4JThread::EventQueue::EventQueue(UpdateFunc* updateFunc, m_drainedCondition(), m_updateFunc(updateFunc), m_threadInitFunc(threadInitFunc), - m_threadName(threadName != nullptr ? threadName : "Unnamed"), + m_threadName(threadName ? threadName : "Unnamed"), m_processor(-1), m_priority(kUnsetPriority), m_busy(false), m_initOnce(), m_stopRequested(false) { - assert(m_updateFunc != nullptr); + assert(m_updateFunc); } C4JThread::EventQueue::~EventQueue() { m_stopRequested.store(true, std::memory_order_release); m_queueCondition.notify_all(); - - if (m_thread) { - (void)m_thread->WaitForCompletion(INFINITE); - } + if (m_thread) (void)m_thread->waitForCompletion(kInfiniteTimeout); } void C4JThread::EventQueue::setProcessor(int proc) { m_processor = proc; - if (m_thread) { - m_thread->SetProcessor(proc); - } + if (m_thread) m_thread->setProcessor(proc); } -void C4JThread::EventQueue::setPriority(int priority) { +void C4JThread::EventQueue::setPriority(ThreadPriority priority) { m_priority = priority; - if (m_thread) { - m_thread->SetPriority(priority); - } + if (m_thread) m_thread->setPriority(priority); } void C4JThread::EventQueue::init() { std::call_once(m_initOnce, [this]() { m_thread = std::make_unique(threadFunc, this, m_threadName.c_str()); - - if (m_processor >= 0) { - m_thread->SetProcessor(m_processor); - } - - if (m_priority != kUnsetPriority) { - m_thread->SetPriority(m_priority); - } - - m_thread->Run(); + if (m_processor >= 0) m_thread->setProcessor(m_processor); + if (m_priority != kUnsetPriority) m_thread->setPriority(m_priority); + m_thread->run(); }); } void C4JThread::EventQueue::sendEvent(Level* pLevel) { init(); - - if (m_stopRequested.load(std::memory_order_acquire)) { - return; - } - + if (m_stopRequested.load(std::memory_order_acquire)) return; { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_queue.push(pLevel); } - m_queueCondition.notify_one(); } void C4JThread::EventQueue::waitForFinish() { init(); - - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); m_drainedCondition.wait(lock, [this] { return m_queue.empty() && !m_busy; }); } int C4JThread::EventQueue::threadFunc(void* lpParam) { - EventQueue* pQueue = static_cast(lpParam); - pQueue->threadPoll(); + static_cast(lpParam)->threadPoll(); return 0; } void C4JThread::EventQueue::threadPoll() { ShutdownManager::HasStarted(ShutdownManager::eEventQueueThreads); - if (m_threadInitFunc != nullptr) { + if (m_threadInitFunc) { try { m_threadInitFunc(); } catch (...) { @@ -779,7 +600,7 @@ void C4JThread::EventQueue::threadPoll() { void* updateParam = nullptr; { - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); m_queueCondition.wait_for( lock, std::chrono::milliseconds(kEventQueueShutdownPollMs), [this] { @@ -787,13 +608,8 @@ void C4JThread::EventQueue::threadPoll() { !m_queue.empty(); }); - if (m_stopRequested.load(std::memory_order_acquire)) { - break; - } - - if (m_queue.empty()) { - continue; - } + if (m_stopRequested.load(std::memory_order_acquire)) break; + if (m_queue.empty()) continue; m_busy = true; updateParam = m_queue.front(); @@ -806,82 +622,60 @@ void C4JThread::EventQueue::threadPoll() { } { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_busy = false; - if (m_queue.empty()) { - m_drainedCondition.notify_all(); - } + if (m_queue.empty()) m_drainedCondition.notify_all(); } } { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); m_busy = false; - std::queue emptyQueue; - m_queue.swap(emptyQueue); + std::queue empty; + m_queue.swap(empty); } m_drainedCondition.notify_all(); ShutdownManager::HasFinished(ShutdownManager::eEventQueueThreads); } -void C4JThread::PushAffinityAllCores() { +void C4JThread::pushAffinityAllCores() { #if defined(_WIN32) - const void* currentThread = ::GetCurrentThread(); - DWORD_PTR processAffinityMask = 0; - DWORD_PTR systemAffinityMask = 0; - - if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinityMask, - &systemAffinityMask) || - processAffinityMask == 0) { + DWORD_PTR processMask = 0, systemMask = 0; + if (!::GetProcessAffinityMask(::GetCurrentProcess(), &processMask, + &systemMask) || + processMask == 0) return; - } - - const DWORD_PTR previousMask = - ::SetThreadAffinityMask(currentThread, processAffinityMask); - - if (previousMask != 0) { - g_affinityMaskStack.push_back(previousMask); - } + const DWORD_PTR prev = + ::SetThreadAffinityMask(::GetCurrentThread(), processMask); + if (prev != 0) g_affinityMaskStack.push_back(prev); #elif defined(__linux__) - cpu_set_t previousMask; - if (::pthread_getaffinity_np(::pthread_self(), sizeof(previousMask), - &previousMask) != 0) { + cpu_set_t prev; + if (::pthread_getaffinity_np(::pthread_self(), sizeof(prev), &prev) != 0) return; - } + g_affinityMaskStack.push_back(prev); - g_affinityMaskStack.push_back(previousMask); - - cpu_set_t allowedMask; - if (::sched_getaffinity(0, sizeof(allowedMask), &allowedMask) != 0) { + cpu_set_t all; + if (::sched_getaffinity(0, sizeof(all), &all) != 0) { g_affinityMaskStack.pop_back(); return; } - - (void)::pthread_setaffinity_np(::pthread_self(), sizeof(allowedMask), - &allowedMask); + (void)::pthread_setaffinity_np(::pthread_self(), sizeof(all), &all); #endif } -void C4JThread::PopAffinity() { +void C4JThread::popAffinity() { #if defined(_WIN32) - if (g_affinityMaskStack.empty()) { - return; - } - - const DWORD_PTR previousMask = g_affinityMaskStack.back(); + if (g_affinityMaskStack.empty()) return; + const DWORD_PTR prev = g_affinityMaskStack.back(); g_affinityMaskStack.pop_back(); - (void)::SetThreadAffinityMask(::GetCurrentThread(), previousMask); + (void)::SetThreadAffinityMask(::GetCurrentThread(), prev); #elif defined(__linux__) - if (g_affinityMaskStack.empty()) { - return; - } - - const cpu_set_t previousMask = g_affinityMaskStack.back(); + if (g_affinityMaskStack.empty()) return; + const cpu_set_t prev = g_affinityMaskStack.back(); g_affinityMaskStack.pop_back(); - (void)::pthread_setaffinity_np(::pthread_self(), sizeof(previousMask), - &previousMask); + (void)::pthread_setaffinity_np(::pthread_self(), sizeof(prev), &prev); #endif -} \ No newline at end of file +} diff --git a/Minecraft.World/Util/C4JThread.h b/Minecraft.World/Util/C4JThread.h index 8fea963f1..3d0ea9688 100644 --- a/Minecraft.World/Util/C4JThread.h +++ b/Minecraft.World/Util/C4JThread.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -37,19 +36,37 @@ inline constexpr int CPU_CORE_LEADERBOARDS = 5; class C4JThread { public: + struct WaitResult { + static constexpr std::uint32_t Signaled = 0; + static constexpr std::uint32_t Timeout = 258; + }; + + enum class ThreadPriority : int { + Idle = -15, + Lowest = -2, + BelowNormal = -1, + Normal = 0, + AboveNormal = 1, + Highest = 2, + TimeCritical = 15 + }; + + static constexpr int kInfiniteTimeout = -1; + static constexpr int kStillActive = 259; + class Event { public: - enum EMode { e_modeAutoClear, e_modeManualClear }; + enum class Mode { AutoClear, ManualClear }; - explicit Event(EMode mode = e_modeAutoClear); + explicit Event(Mode mode = Mode::AutoClear); ~Event() = default; - void Set(); - void Clear(); - std::uint32_t WaitForSignal(int timeoutMs); + void set(); + void clear(); + std::uint32_t waitForSignal(int timeoutMs); private: - EMode m_mode; + Mode m_mode; std::mutex m_mutex; std::condition_variable m_condition; bool m_signaled; @@ -57,21 +74,21 @@ public: class EventArray { public: - enum EMode { e_modeAutoClear, e_modeManualClear }; + enum class Mode { AutoClear, ManualClear }; - explicit EventArray(int size, EMode mode = e_modeAutoClear); + explicit EventArray(int size, Mode mode = Mode::AutoClear); - void Set(int index); - void Clear(int index); - void SetAll(); - void ClearAll(); - std::uint32_t WaitForAll(int timeoutMs); - std::uint32_t WaitForAny(int timeoutMs); - std::uint32_t WaitForSingle(int index, int timeoutMs); + void set(int index); + void clear(int index); + void setAll(); + void clearAll(); + std::uint32_t waitForAll(int timeoutMs); + std::uint32_t waitForAny(int timeoutMs); + std::uint32_t waitForSingle(int index, int timeoutMs); private: int m_size; - EMode m_mode; + Mode m_mode; std::mutex m_mutex; std::condition_variable m_condition; std::uint32_t m_signaledMask; @@ -90,7 +107,7 @@ public: EventQueue& operator=(const EventQueue&) = delete; void setProcessor(int proc); - void setPriority(int priority); + void setPriority(ThreadPriority priority); void sendEvent(Level* pLevel); void waitForFinish(); @@ -108,7 +125,7 @@ public: ThreadInitFunc* m_threadInitFunc; std::string m_threadName; int m_processor; - int m_priority; + ThreadPriority m_priority; bool m_busy; std::once_flag m_initOnce; std::atomic m_stopRequested; @@ -122,24 +139,25 @@ public: C4JThread(const C4JThread&) = delete; C4JThread& operator=(const C4JThread&) = delete; - void Run(); + void run(); - [[nodiscard]] bool isRunning() const noexcept { return m_isRunning.load(); } + [[nodiscard]] bool isRunning() const noexcept { + return m_isRunning.load(std::memory_order_acquire); + } [[nodiscard]] bool hasStarted() const noexcept { - return m_hasStarted.load(); + return m_hasStarted.load(std::memory_order_acquire); } - void SetProcessor(int proc); - void SetPriority(int priority); + void setProcessor(int proc); + void setPriority(ThreadPriority priority); - std::uint32_t WaitForCompletion(int timeoutMs); - [[nodiscard]] int GetExitCode() const noexcept; + std::uint32_t waitForCompletion(int timeoutMs); + [[nodiscard]] int getExitCode() const noexcept; [[nodiscard]] const char* getName() const noexcept { return m_threadName.c_str(); } - static void Sleep(int millisecs); static C4JThread* getCurrentThread() noexcept; static bool isMainThread() noexcept; @@ -148,11 +166,16 @@ public: return pThread ? pThread->getName() : "(4J) Unknown thread"; } - static void SetThreadName(std::uint32_t threadId, const char* threadName); - static void SetCurrentThreadName(const char* threadName); + static void setThreadName(std::uint32_t threadId, const char* threadName); + static void setCurrentThreadName(const char* threadName); - static void PushAffinityAllCores(); - static void PopAffinity(); + static void pushAffinityAllCores(); + static void popAffinity(); + + // TODO(C++26): When we switch to C++26, replace EventQueue with + // std::execution (senders/receivers) for structured concurrency. + // TODO(C++26): When we switch to C++26, use std::hazard_pointer / std::rcu + // for lock-free data structure reclamation. private: static void entryPoint(C4JThread* pThread); @@ -171,8 +194,8 @@ private: std::unique_ptr m_completionFlag; std::atomic m_requestedProcessor; - std::atomic m_requestedPriority; + std::atomic m_requestedPriority; std::atomic m_nativeTid; static thread_local C4JThread* ms_currentThread; -}; \ No newline at end of file +};