diff --git a/src/engine/client/clientstate.cpp b/src/engine/client/clientstate.cpp index 3e229aea..f7c42b5a 100644 --- a/src/engine/client/clientstate.cpp +++ b/src/engine/client/clientstate.cpp @@ -135,7 +135,7 @@ void CClientState::VConnectionClosing(CClientState* thisptr, const char* szReaso // Delay execution to the next frame; this is required to avoid a rare crash. // Cannot reload playlists while still disconnecting. - g_TaskScheduler->Dispatch([]() + g_TaskQueue.Dispatch([]() { // Reload the local playlist to override the cached // one from the server we got disconnected from. diff --git a/src/engine/host.cpp b/src/engine/host.cpp index 1390ce80..0ffb69b5 100644 --- a/src/engine/host.cpp +++ b/src/engine/host.cpp @@ -61,15 +61,15 @@ Runs all active servers */ void _Host_RunFrame(void* unused, float time) { - for (IFrameTask* const& task : g_FrameTasks) + for (IFrameTask* const& task : g_TaskQueueList) { task->RunFrame(); } - g_FrameTasks.erase(std::remove_if(g_FrameTasks.begin(), g_FrameTasks.end(), [](const IFrameTask* task) + g_TaskQueueList.erase(std::remove_if(g_TaskQueueList.begin(), g_TaskQueueList.end(), [](const IFrameTask* task) { return task->IsFinished(); - }), g_FrameTasks.end()); + }), g_TaskQueueList.end()); #ifndef DEDICATED g_TextOverlay.ShouldDraw(time); diff --git a/src/engine/server/sv_main.cpp b/src/engine/server/sv_main.cpp index 998e5ee0..f4a8df16 100644 --- a/src/engine/server/sv_main.cpp +++ b/src/engine/server/sv_main.cpp @@ -30,7 +30,7 @@ void SV_IsClientBanned(CClient* pClient, const string& svIPAddr, { if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([pClient, svError, svIPAddr, nNucleusID, nPort] + g_TaskQueue.Dispatch([pClient, svError, svIPAddr, nNucleusID, nPort] { // Make sure client isn't already disconnected, // and that if there is a valid netchannel, that @@ -66,7 +66,7 @@ void SV_ProcessBulkCheck(const CBanSystem::BannedList_t* pBannedVec, const bool if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([outBannedVec] + g_TaskQueue.Dispatch([outBannedVec] { SV_CheckForBan(outBannedVec, true); }, 0); diff --git a/src/engine/sys_dll.cpp b/src/engine/sys_dll.cpp index 4365946b..9dae9a20 100644 --- a/src/engine/sys_dll.cpp +++ b/src/engine/sys_dll.cpp @@ -118,7 +118,7 @@ bool CModAppSystemGroup::StaticCreate(CModAppSystemGroup* pModAppSystemGroup) cv->EnableDevCvars(); } - g_FrameTasks.push_back(std::move(g_TaskScheduler)); + g_TaskQueueList.push_back(&g_TaskQueue); g_bAppSystemInit = true; return CModAppSystemGroup__Create(pModAppSystemGroup); diff --git a/src/gameui/IBrowser.cpp b/src/gameui/IBrowser.cpp index 09cd72f9..7fc5e483 100644 --- a/src/gameui/IBrowser.cpp +++ b/src/gameui/IBrowser.cpp @@ -368,7 +368,7 @@ void CBrowser::RefreshServerList(void) std::string svServerListMessage; g_ServerListManager.RefreshServerList(svServerListMessage); - g_TaskScheduler->Dispatch([&, svServerListMessage] + g_TaskQueue.Dispatch([&, svServerListMessage] { SetServerListMessage(svServerListMessage.c_str()); }, 0); @@ -774,7 +774,7 @@ void CBrowser::SendHostingPostRequest(const NetGameServer_t& gameServer) const bool result = g_MasterServer.PostServerHost(hostRequestMessage, hostToken, hostIp, gameServer); - g_TaskScheduler->Dispatch([&, result, hostRequestMessage, hostToken, hostIp] + g_TaskQueue.Dispatch([&, result, hostRequestMessage, hostToken, hostIp] { InstallHostingDetails(result, hostRequestMessage.c_str(), hostToken.c_str(), hostIp); }, 0); diff --git a/src/networksystem/listmanager.cpp b/src/networksystem/listmanager.cpp index fef7e3d5..06949f85 100644 --- a/src/networksystem/listmanager.cpp +++ b/src/networksystem/listmanager.cpp @@ -59,7 +59,7 @@ void CServerListManager::LaunchServer(const bool bChangeLevel) const { if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([this, bChangeLevel]() + g_TaskQueue.Dispatch([this, bChangeLevel]() { this->LaunchServer(bChangeLevel); }, 0); @@ -90,7 +90,7 @@ void CServerListManager::ConnectToServer(const string& svIp, const int nPort, co { if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([this, svIp, nPort, svNetKey]() + g_TaskQueue.Dispatch([this, svIp, nPort, svNetKey]() { this->ConnectToServer(svIp, nPort, svNetKey); }, 0); @@ -113,7 +113,7 @@ void CServerListManager::ConnectToServer(const string& svServer, const string& s { if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([this, svServer, svNetKey]() + g_TaskQueue.Dispatch([this, svServer, svNetKey]() { this->ConnectToServer(svServer, svNetKey); }, 0); @@ -134,7 +134,6 @@ void CServerListManager::ConnectToServer(const string& svServer, const string& s void CServerListManager::ProcessCommand(const char* pszCommand) const { Cbuf_AddText(Cbuf_GetCurrentPlayer(), pszCommand, cmd_source_t::kCommandSrcCode); - //g_TaskScheduler->Dispatch(Cbuf_Execute, 0); // Run in main thread. } CServerListManager g_ServerListManager; \ No newline at end of file diff --git a/src/public/iframetask.h b/src/public/iframetask.h index cd901a1d..248c86f9 100644 --- a/src/public/iframetask.h +++ b/src/public/iframetask.h @@ -1,11 +1,12 @@ #ifndef TIER0_IFRAMETASK_H #define TIER0_IFRAMETASK_H -struct ScheduledTasks_s +struct QueuedTasks_s { - int m_nDelayedFrames; + unsigned int m_nDelayedFrames; std::function m_rFunctor; - ScheduledTasks_s(int frames, std::function functor) + + QueuedTasks_s(unsigned int frames, std::function functor) { m_nDelayedFrames = frames; m_rFunctor = functor; @@ -16,6 +17,7 @@ abstract_class IFrameTask { public: virtual ~IFrameTask() {} + virtual void RunFrame() = 0; virtual bool IsFinished() const = 0; }; diff --git a/src/public/tier0/frametask.h b/src/public/tier0/frametask.h index 126e76df..01e7c2f9 100644 --- a/src/public/tier0/frametask.h +++ b/src/public/tier0/frametask.h @@ -8,7 +8,9 @@ // Committed tasks are scheduled to execute after 'i' frames. // ---------------------------------------------------------------------------- // A use case for scheduling tasks in the main thread would be (for example) -// calling 'KeyValues::ParsePlaylists(...)' from the render thread. +// performing a web request in a separate thread, and apply the results (such as +// server lists in the browser) onto the imgui panels which are created/drawn in +// the main thread //=============================================================================// class CFrameTask : public IFrameTask { @@ -17,14 +19,14 @@ public: virtual void RunFrame(); virtual bool IsFinished() const; - void Dispatch(std::function functor, int frames); + void Dispatch(std::function functor, unsigned int frames); private: mutable std::mutex m_Mutex; - std::list m_ScheduledTasks; + std::list m_QueuedTasks; }; -extern std::list g_FrameTasks; -extern CFrameTask* g_TaskScheduler; +extern std::list g_TaskQueueList; +extern CFrameTask g_TaskQueue; #endif // TIER0_FRAMETASK_H diff --git a/src/tier0/frametask.cpp b/src/tier0/frametask.cpp index 899f0cda..a2f3903d 100644 --- a/src/tier0/frametask.cpp +++ b/src/tier0/frametask.cpp @@ -13,20 +13,24 @@ void CFrameTask::RunFrame() { std::lock_guard l(m_Mutex); - for (auto& delay : m_ScheduledTasks) + + for (QueuedTasks_s& delay : m_QueuedTasks) { - delay.m_nDelayedFrames = (std::max)(delay.m_nDelayedFrames - 1, 0); if (delay.m_nDelayedFrames == 0) { delay.m_rFunctor(); } + + --delay.m_nDelayedFrames; } - auto newEnd = std::remove_if(m_ScheduledTasks.begin(), m_ScheduledTasks.end(), [](const ScheduledTasks_s& delay) + const auto newEnd = std::remove_if(m_QueuedTasks.begin(), m_QueuedTasks.end(), + [](const QueuedTasks_s& delay) { return delay.m_nDelayedFrames == 0; }); - m_ScheduledTasks.erase(newEnd, m_ScheduledTasks.end()); + + m_QueuedTasks.erase(newEnd, m_QueuedTasks.end()); } //----------------------------------------------------------------------------- @@ -43,12 +47,12 @@ bool CFrameTask::IsFinished() const // Input : functor - // frames - //----------------------------------------------------------------------------- -void CFrameTask::Dispatch(std::function functor, int frames) +void CFrameTask::Dispatch(std::function functor, unsigned int frames) { std::lock_guard l(m_Mutex); - m_ScheduledTasks.emplace_back(frames, functor); + m_QueuedTasks.emplace_back(frames, functor); } //----------------------------------------------------------------------------- -std::list g_FrameTasks; -CFrameTask* g_TaskScheduler = new CFrameTask(); +std::list g_TaskQueueList; +CFrameTask g_TaskQueue; diff --git a/src/vscript/vscript.cpp b/src/vscript/vscript.cpp index 804b3e9d..39ca5e03 100644 --- a/src/vscript/vscript.cpp +++ b/src/vscript/vscript.cpp @@ -133,7 +133,7 @@ void Script_Execute(const SQChar* code, const SQCONTEXT context) if (!ThreadInMainThread()) { const string scode(code); - g_TaskScheduler->Dispatch([scode, context]() + g_TaskQueue.Dispatch([scode, context]() { Script_Execute(scode.c_str(), context); }, 0);