mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-14 03:52:30 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
382
src/event/Scheduler.cpp
Normal file
382
src/event/Scheduler.cpp
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
#include "event/Scheduler.hpp"
|
||||
#include "event/Context.hpp"
|
||||
#include "event/Event.hpp"
|
||||
#include "event/EvtContext.hpp"
|
||||
#include "event/EvtThread.hpp"
|
||||
#include "event/Input.hpp"
|
||||
#include "event/Queue.hpp"
|
||||
#include "event/Synthesize.hpp"
|
||||
#include "event/Timer.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <common/Call.hpp>
|
||||
#include <common/Prop.hpp>
|
||||
#include <common/Time.hpp>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
#include <storm/Thread.hpp>
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
#include "event/mac/Event.h"
|
||||
#endif
|
||||
|
||||
void DestroySchedulerThread(uint32_t a1) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
HEVENTCONTEXT IEvtSchedulerCreateContext(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags) {
|
||||
if (idleTime < 1) {
|
||||
idleTime = 1;
|
||||
}
|
||||
|
||||
char contextName[256];
|
||||
void* callContext = nullptr;
|
||||
|
||||
if (debugFlags & 0x1) {
|
||||
SStrPrintf(contextName, 256, "Context: interactive = %u, idleTime = %u", interactive, idleTime);
|
||||
callContext = OsCallInitializeContext(contextName);
|
||||
}
|
||||
|
||||
void* m = SMemAlloc(sizeof(EvtContext), __FILE__, __LINE__, 0);
|
||||
|
||||
EvtContext* context;
|
||||
|
||||
if (m) {
|
||||
context = new (m) EvtContext(
|
||||
interactive != 0 ? 2 : 0,
|
||||
idleTime,
|
||||
interactive != 0 ? 1000 : 1,
|
||||
callContext,
|
||||
(debugFlags >> 1) & 1
|
||||
);
|
||||
} else {
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
SInterlockedIncrement(&Event::s_interactiveCount);
|
||||
}
|
||||
|
||||
if (initializeHandler) {
|
||||
IEvtQueueRegister(context, EVENT_ID_INITIALIZE, initializeHandler, 0, 1000.0);
|
||||
}
|
||||
|
||||
if (destroyHandler) {
|
||||
IEvtQueueRegister(context, EVENT_ID_DESTROY, destroyHandler, 0, 1000.0);
|
||||
}
|
||||
|
||||
return AttachContextToThread(context);
|
||||
}
|
||||
|
||||
void IEvtSchedulerInitialize(int32_t threadCount, int32_t netServer) {
|
||||
if (Event::s_threadSlotCount) {
|
||||
// SErrDisplayAppFatal("IEvtScheduler already initialized");
|
||||
}
|
||||
|
||||
Event::s_netServer = netServer;
|
||||
|
||||
// TODO
|
||||
// Thread::s_originalThreadPriority = SGetCurrentThreadPriority();
|
||||
|
||||
int32_t threadSlotCount = 1;
|
||||
|
||||
while (threadSlotCount < threadCount) {
|
||||
threadSlotCount *= 2;
|
||||
}
|
||||
|
||||
Event::s_threadSlotCount = threadSlotCount;
|
||||
|
||||
// Allocate SCritSects for each thread slot
|
||||
int32_t v4 = sizeof(SCritSect) * threadSlotCount;
|
||||
|
||||
void* v5 = SMemAlloc((v4 + 4), ".\\EvtSched.cpp", 791, 0);
|
||||
|
||||
if (v5) {
|
||||
Event::s_threadSlotCritsects = new (v5) SCritSect[threadSlotCount];
|
||||
} else {
|
||||
Event::s_threadSlotCritsects = nullptr;
|
||||
}
|
||||
|
||||
// Allocate EvtThread pointers for each thread slot
|
||||
Event::s_threadSlots = static_cast<EvtThread**>(SMemAlloc(sizeof(EvtThread*) * threadSlotCount, __FILE__, __LINE__, 0));
|
||||
memset(Event::s_threadSlots, 0, sizeof(EvtThread*) * threadSlotCount);
|
||||
|
||||
Event::s_startEvent.Reset();
|
||||
Event::s_shutdownEvent.Reset();
|
||||
|
||||
Event::s_mainThread = InitializeSchedulerThread();
|
||||
|
||||
for (int32_t i = 0; i < threadCount - 1; ++i) {
|
||||
void* m = SMemAlloc(sizeof(SThread), __FILE__, __LINE__, 0);
|
||||
|
||||
SThread* thread;
|
||||
|
||||
if (m) {
|
||||
thread = new (m) SThread();
|
||||
} else {
|
||||
thread = nullptr;
|
||||
}
|
||||
|
||||
Event::s_schedulerThreads.SetCount(Event::s_schedulerThreads.Count() + 1);
|
||||
|
||||
Event::s_schedulerThreads[Event::s_schedulerThreads.Count() - 1] = thread;
|
||||
|
||||
char threadName[16];
|
||||
SStrPrintf(threadName, 16, "EvtSched#%d", i);
|
||||
|
||||
if (!SThread::Create(&SchedulerThreadProc, 0, *thread, threadName, 0)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IEvtSchedulerProcess() {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
Event::s_startEvent.Set();
|
||||
|
||||
SchedulerThreadProc(1);
|
||||
|
||||
Event::s_mainThread = 0;
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
Event::s_startEvent.Set();
|
||||
|
||||
if (OsInputIsUsingCocoaEventLoop()) {
|
||||
PropSelectContext(0);
|
||||
|
||||
Event::s_startEvent.Wait(0xFFFFFFFF);
|
||||
|
||||
uintptr_t v0 = SGetCurrentThreadId();
|
||||
char v2[64];
|
||||
SStrPrintf(v2, 64, "Engine %x", v0);
|
||||
|
||||
OsCallInitialize(v2);
|
||||
|
||||
RunCocoaEventLoop();
|
||||
|
||||
DestroySchedulerThread(Event::s_mainThread);
|
||||
OsCallDestroy();
|
||||
|
||||
Event::s_mainThread = 0;
|
||||
} else {
|
||||
// Legacy
|
||||
// sub_890180(1);
|
||||
// dword_141B3C8 = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IEvtSchedulerShutdown() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
uint32_t InitializeSchedulerThread() {
|
||||
SInterlockedIncrement(&Event::s_threadListContention);
|
||||
|
||||
Event::s_threadListCritsect.Enter();
|
||||
|
||||
uint32_t slot = Event::s_threadSlotCount;
|
||||
|
||||
for (int32_t i = 0; i < Event::s_threadSlotCount; ++i) {
|
||||
if (slot == Event::s_threadSlotCount
|
||||
|| Event::s_threadSlots[i] == nullptr
|
||||
|| Event::s_threadSlots[i]->m_threadCount < Event::s_threadSlots[slot]->m_threadCount)
|
||||
{
|
||||
slot = i;
|
||||
|
||||
if (!Event::s_threadSlots[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EvtThread* v4 = Event::s_threadSlots[slot];
|
||||
|
||||
if (!v4) {
|
||||
v4 = Event::s_threadList.NewNode(1, 0, 0x8);
|
||||
|
||||
v4->m_threadCount = 0;
|
||||
v4->m_weightTotal = 0;
|
||||
v4->m_weightAvg = 0;
|
||||
v4->m_contextCount = 0;
|
||||
v4->m_rebalance = 0;
|
||||
v4->m_threadSlot = slot;
|
||||
|
||||
Event::s_threadSlotCritsects[slot].Enter();
|
||||
|
||||
Event::s_threadSlots[slot] = v4;
|
||||
|
||||
Event::s_threadSlotCritsects[slot].Leave();
|
||||
}
|
||||
|
||||
++v4->m_threadCount;
|
||||
|
||||
Event::s_threadListCritsect.Leave();
|
||||
|
||||
SInterlockedDecrement(&Event::s_threadListContention);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
bool SchedulerMainProcess() {
|
||||
return SchedulerThreadProcProcess(Event::s_mainThread) != 0;
|
||||
}
|
||||
|
||||
uint32_t SchedulerThreadProc(void* mainThread) {
|
||||
uint32_t v1;
|
||||
|
||||
if (mainThread) {
|
||||
v1 = Event::s_mainThread;
|
||||
} else {
|
||||
v1 = InitializeSchedulerThread();
|
||||
}
|
||||
|
||||
PropSelectContext(0);
|
||||
|
||||
Event::s_startEvent.Wait(0xFFFFFFFF);
|
||||
|
||||
uintptr_t v2 = SGetCurrentThreadId();
|
||||
char v4[64];
|
||||
SStrPrintf(v4, 64, "Engine %x", v2);
|
||||
|
||||
OsCallInitialize(v4);
|
||||
|
||||
while (!SchedulerThreadProcProcess(v1));
|
||||
|
||||
DestroySchedulerThread(v1);
|
||||
OsCallDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SchedulerThreadProcProcess(uint32_t a1) {
|
||||
// TODO
|
||||
// if (SGetCurrentThreadPriority() != Event::s_originalThreadPriority) {
|
||||
// SSetCurrentThreadPriority(Event::s_originalThreadPriority);
|
||||
// }
|
||||
|
||||
if (!Event::s_shutdownEvent.Wait(0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
EvtContext* context = GetNextContext(a1);
|
||||
|
||||
int32_t v11;
|
||||
|
||||
if (context) {
|
||||
v11 = context->m_schedNextWakeTime.m_val - OsGetAsyncTimeMs();
|
||||
|
||||
if (v11 < 0) {
|
||||
v11 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t v14;
|
||||
|
||||
if (Event::s_netServer) {
|
||||
if (v11 == -1) {
|
||||
v11 = 100;
|
||||
}
|
||||
|
||||
OsNetPump(v11);
|
||||
|
||||
v14 = 258;
|
||||
} else {
|
||||
v14 = Event::s_threadSlots[a1]->m_wakeEvent.Wait(v11);
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PropSelectContext(context->m_propContext);
|
||||
PropSet(PROP_EVENTCONTEXT, &context->m_id);
|
||||
OsCallSetContext(context->m_callContext);
|
||||
|
||||
uint32_t currTime = OsGetAsyncTimeMs();
|
||||
uint32_t v19 = context->m_id;
|
||||
|
||||
if (v14 == 258) {
|
||||
if (SynthesizeInitialize(context)) {
|
||||
if (context->m_startWatchdog) {
|
||||
// nullsub_5(20, 1);
|
||||
// *a2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t v9 = (currTime - context->m_schedLastIdle);
|
||||
context->m_schedLastIdle = currTime;
|
||||
double elapsedSec = v9 * 0.001;
|
||||
|
||||
// TODO
|
||||
// FrameTime::Update(currTime, elapsedSec);
|
||||
|
||||
IEvtTimerDispatch(context);
|
||||
|
||||
if (context->m_schedFlags & 0x2) {
|
||||
int32_t shutdown = 0;
|
||||
IEvtInputProcess(context, &shutdown);
|
||||
|
||||
if (shutdown) {
|
||||
context->m_critsect.Enter();
|
||||
|
||||
if (context->m_schedState == EvtContext::SCHEDSTATE_ACTIVE) {
|
||||
context->m_schedState = EvtContext::SCHEDSTATE_CLOSED;
|
||||
}
|
||||
|
||||
context->m_critsect.Leave();
|
||||
|
||||
IEvtSchedulerShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
SynthesizePoll(context);
|
||||
IEvtQueueDispatchAll(context);
|
||||
SynthesizeIdle(context, currTime, elapsedSec);
|
||||
SynthesizePaint(context);
|
||||
}
|
||||
|
||||
if (a1 == Event::s_mainThread) {
|
||||
// TODO
|
||||
// dword_B417C4 = 0;
|
||||
}
|
||||
|
||||
context->m_critsect.Enter();
|
||||
|
||||
uint32_t closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED;
|
||||
|
||||
context->m_critsect.Leave();
|
||||
|
||||
if (closed) {
|
||||
DetachContextFromThread(a1, context);
|
||||
SynthesizeDestroy(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t nextDelay;
|
||||
|
||||
if (context->m_schedFlags & 0x4) {
|
||||
nextDelay = 0;
|
||||
} else {
|
||||
int32_t v15 = IEvtTimerGetNextTime(context, currTime);
|
||||
int32_t v16 = context->m_schedIdleTime;
|
||||
|
||||
nextDelay = v15;
|
||||
|
||||
if (v16 != context->m_schedInitialIdleTime) {
|
||||
nextDelay = context->m_schedIdleTime;
|
||||
}
|
||||
|
||||
nextDelay = std::min(
|
||||
nextDelay,
|
||||
std::max((uint32_t)0, v16 + context->m_schedLastIdle - currTime)
|
||||
);
|
||||
}
|
||||
|
||||
OsCallResetContext(context->m_callContext);
|
||||
PropSelectContext(nullptr);
|
||||
PutContext(nextDelay + currTime, context->m_schedSmoothWeight, context, a1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue