Refactor C4JThread: modernise API naming and replace Windows constants

Rename all PascalCase methods to camelCase, replace Windows macro constants with C++ constexpr members, convert ThreadPriority to enum class, remove unused Sleep(), fix memory ordering on inline accessors, extract platform code into helpers.
This commit is contained in:
MatthewBeshay 2026-03-31 01:01:25 +11:00
parent 156a23d744
commit e911e07a58
19 changed files with 458 additions and 641 deletions

View file

@ -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<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();
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;

View file

@ -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
}

View file

@ -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<std::mutex> 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: {

View file

@ -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();
}

View file

@ -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;

View file

@ -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(

View file

@ -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 "

View file

@ -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

View file

@ -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) {

View file

@ -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<unsigned int>(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) {

View file

@ -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,

View file

@ -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,

View file

@ -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
}

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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();

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,6 @@
#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <limits>
#include <memory>
#include <mutex>
#include <queue>
@ -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<bool> 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<Event> m_completionFlag;
std::atomic<int> m_requestedProcessor;
std::atomic<int> m_requestedPriority;
std::atomic<ThreadPriority> m_requestedPriority;
std::atomic<std::int64_t> m_nativeTid;
static thread_local C4JThread* ms_currentThread;
};
};