From 79974b3dff403b55bfaedc5243bfcef1afe7462f Mon Sep 17 00:00:00 2001 From: Nefarius Date: Sat, 19 Jul 2014 11:45:14 +0200 Subject: [PATCH] Swapped out custom thread creation mechanism with SMs thread worker --- extensions/curl/extension.cpp | 63 ++++++++++------------------------- extensions/curl/extension.h | 4 +-- 2 files changed, 19 insertions(+), 48 deletions(-) diff --git a/extensions/curl/extension.cpp b/extensions/curl/extension.cpp index 2ac589bc1..428094f06 100644 --- a/extensions/curl/extension.cpp +++ b/extensions/curl/extension.cpp @@ -100,8 +100,9 @@ bool CurlExt::SDK_OnLoad(char *error, size_t maxlength, bool late) // Register game listeners plsys->AddPluginsListener(this); + g_SessionManager.Initialize(); smutils->AddGameFrameHook(&OnGameFrame); - + return true; } @@ -574,6 +575,11 @@ const sp_nativeinfo_t curlext_natives[] = void HTTPSessionManager::PluginUnloaded(IPlugin *plugin) { // Wait for running requests to finish + /* NOTE: when a plugin gets unloaded all associated handles get + * automatically destroyed, so running threads may access invalid + * memory and crash the host process. This blocking "solution" may + * have to be re factored to a better solution. + */ { ke::AutoLock lock(&threads_); @@ -605,10 +611,7 @@ void HTTPSessionManager::PostAndDownload(IPluginContext *pCtx, request.url = url; request.contextPack = contextPack; - { - ke::AutoLock lock(&requests_); - this->requests.append(request); - } + m_pWorker->MakeThread(new HTTPAsyncRequestHandler(request), Thread_AutoRelease); } void HTTPSessionManager::Download(IPluginContext *pCtx, @@ -624,10 +627,7 @@ void HTTPSessionManager::Download(IPluginContext *pCtx, request.url = url; request.contextPack = contextPack; - { - ke::AutoLock lock(&requests_); - this->requests.append(request); - } + m_pWorker->MakeThread(new HTTPAsyncRequestHandler(request), Thread_AutoRelease); } void HTTPSessionManager::BurnSessionHandle(IPluginContext *pCtx, @@ -688,43 +688,6 @@ void HTTPSessionManager::RunFrame() callbacks_.DoUnlock(); } - // Try to fire up some new asynchronous requests - if (requests_.DoTryLock()) - { - // NOTE: this is my "burst thread creation" solution - // Using a thread pool is slow as it executes the threads - // sequentially and not parallel. - // Not using a thread pool might cause SRCDS to crash, so - // we are spawning just a few threads every frame to not - // affect performance too much and still having the advantage - // of parallel execution. - for (unsigned int i = 0; i < iMaxRequestsPerFrame; i++) - { - if (!requests.empty()) - { - // Create new thread object - HTTPAsyncRequestHandler *async = - new HTTPAsyncRequestHandler(requests.back()); - HandleError herr; - IPlugin *parent = - plsys->PluginFromHandle(requests.back().plugin, &herr); - // Skip requests with unloaded parent plugin - if (parent != NULL && herr != HandleError_Freed) - { - // Create new thread - IThreadHandle *pThread = - threader->MakeThread(async, Thread_Default); - // Save thread handle - threads.append(pThread); - } - // Remove request as it's being handled now - requests.pop(); - } - } - - requests_.DoUnlock(); - } - // Do some quick "garbage collection" on finished threads this->RemoveFinishedThreads(); } @@ -739,6 +702,8 @@ void HTTPSessionManager::Shutdown() ke::AutoLock lock(&callbacks_); this->callbacks.clear(); } + + threader->DestroyWorker(m_pWorker); } void HTTPSessionManager::AddCallback(HTTPRequest request) @@ -770,6 +735,12 @@ void HTTPSessionManager::RemoveFinishedThreads() } } +void HTTPSessionManager::Initialize() +{ + m_pWorker = threader->MakeWorker(NULL, true); + m_pWorker->Start(); +} + void HTTPSessionManager::HTTPAsyncRequestHandler::RunThread(IThreadHandle *pHandle) { HandleError herr; diff --git a/extensions/curl/extension.h b/extensions/curl/extension.h index b3872a139..f4af982dd 100644 --- a/extensions/curl/extension.h +++ b/extensions/curl/extension.h @@ -169,6 +169,7 @@ public: } ~HTTPSessionManager() {} + void Initialize(); void Shutdown(); void PluginUnloaded(IPlugin *plugin); void RunFrame(); @@ -213,8 +214,7 @@ private: void AddCallback(HTTPRequest request); static const unsigned int iMaxRequestsPerFrame = 20; - ke::ConditionVariable requests_; - ke::Vector requests; + IThreadWorker *m_pWorker; ke::ConditionVariable threads_; ke::LinkedList threads; ke::ConditionVariable callbacks_;