From 94acac91a0eb95d8cc9a256d904377a3d53fe282 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 23 Nov 2017 15:47:38 +0100 Subject: [PATCH] Overhauled job system The engine now takes `std::shared_ptr`, this will ensure the appropriate lifetime of the given parameters, it also allows for proper destruction. Remove the now obsolete `IFetcher` interface and `CFetcher` class. Also adds some locks to `CUpdater`, previously it didn't have any locks at all. --- src/engine/client/client.cpp | 33 ++- src/engine/client/client.h | 12 +- src/engine/client/fetcher.cpp | 227 ++++++------------- src/engine/client/fetcher.h | 54 ++++- src/engine/client/updater.cpp | 143 ++++++++---- src/engine/client/updater.h | 23 +- src/engine/engine.h | 13 +- src/engine/fetcher.h | 44 ---- src/engine/server/server.cpp | 14 +- src/engine/server/server.h | 2 +- src/engine/shared/engine.cpp | 28 +-- src/engine/shared/jobs.cpp | 47 ++-- src/engine/shared/jobs.h | 43 ++-- src/engine/shared/masterserver.cpp | 17 +- src/engine/updater.h | 2 +- src/game/client/components/menus_browser.cpp | 8 +- src/game/client/components/sounds.cpp | 31 +-- src/game/client/components/sounds.h | 13 +- src/game/server/score.h | 12 +- 19 files changed, 379 insertions(+), 387 deletions(-) delete mode 100644 src/engine/fetcher.h diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b61906024..ce6990697 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1506,7 +1506,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) char aEscaped[128]; str_format(aFilename, sizeof(aFilename), "%s_%08x.map", pMap, MapCrc); - Fetcher()->Escape(aEscaped, sizeof(aEscaped), aFilename); + EscapeUrl(aEscaped, sizeof(aEscaped), aFilename); str_format(aUrl, sizeof(aUrl), "%s/", g_Config.m_ClDDNetMapDownloadUrl); // We only trust our own custom-selected CAs for our own servers. @@ -1518,7 +1518,8 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) str_append(aUrl, aEscaped, sizeof(aUrl)); - m_pMapdownloadTask = Fetcher()->FetchFile(aUrl, m_aMapdownloadFilename, IStorage::TYPE_SAVE, UseDDNetCA, true); + m_pMapdownloadTask = std::make_shared(Storage(), aUrl, m_aMapdownloadFilename, IStorage::TYPE_SAVE, UseDDNetCA, true); + Engine()->AddJob(m_pMapdownloadTask); } else SendMapRequest(); @@ -2089,7 +2090,6 @@ void CClient::ResetMapDownload() if(m_pMapdownloadTask) { m_pMapdownloadTask->Abort(); - m_pMapdownloadTask->Destroy(); m_pMapdownloadTask = NULL; } m_MapdownloadFile = 0; @@ -2135,7 +2135,6 @@ void CClient::ResetDDNetInfo() if(m_pDDNetInfoTask) { m_pDDNetInfoTask->Abort(); - m_pDDNetInfoTask->Destroy(); m_pDDNetInfoTask = NULL; } } @@ -2476,33 +2475,31 @@ void CClient::Update() if(m_pMapdownloadTask) { - if(m_pMapdownloadTask->State() == IFetchTask::STATE_DONE) + if(m_pMapdownloadTask->State() == CFetchTask::STATE_DONE) FinishMapDownload(); - else if(m_pMapdownloadTask->State() == IFetchTask::STATE_ERROR) + else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ERROR) { dbg_msg("webdl", "http failed, falling back to gameserver"); ResetMapDownload(); SendMapRequest(); } - else if(m_pMapdownloadTask->State() == IFetchTask::STATE_ABORTED) + else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ABORTED) { - m_pMapdownloadTask->Destroy(); m_pMapdownloadTask = NULL; } } if(m_pDDNetInfoTask) { - if(m_pDDNetInfoTask->State() == IFetchTask::STATE_DONE) + if(m_pDDNetInfoTask->State() == CFetchTask::STATE_DONE) FinishDDNetInfo(); - else if(m_pDDNetInfoTask->State() == IFetchTask::STATE_ERROR) + else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ERROR) { dbg_msg("ddnet-info", "download failed"); ResetDDNetInfo(); } - else if(m_pDDNetInfoTask->State() == IFetchTask::STATE_ABORTED) + else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ABORTED) { - m_pDDNetInfoTask->Destroy(); m_pDDNetInfoTask = NULL; } } @@ -2532,7 +2529,6 @@ void CClient::RegisterInterfaces() Kernel()->RegisterInterface(static_cast(&m_GhostRecorder), false); Kernel()->RegisterInterface(static_cast(&m_GhostLoader), false); Kernel()->RegisterInterface(static_cast(&m_ServerBrowser), false); - Kernel()->RegisterInterface(static_cast(&m_Fetcher), false); #if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__) Kernel()->RegisterInterface(static_cast(&m_Updater), false); #endif @@ -2551,7 +2547,6 @@ void CClient::InitInterfaces() m_pInput = Kernel()->RequestInterface(); m_pMap = Kernel()->RequestInterface(); m_pMasterServer = Kernel()->RequestInterface(); - m_pFetcher = Kernel()->RequestInterface(); #if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__) m_pUpdater = Kernel()->RequestInterface(); #endif @@ -2561,7 +2556,7 @@ void CClient::InitInterfaces() m_ServerBrowser.SetBaseInfo(&m_NetClient[2], m_pGameClient->NetVersion()); - m_Fetcher.Init(); + FetcherInit(); #if !defined(CONF_PLATFORM_MACOSX) && !defined(__ANDROID__) m_Updater.Init(); @@ -3632,15 +3627,13 @@ void CClient::RequestDDNetInfo() if(g_Config.m_BrIndicateFinished) { char aEscaped[128]; - Fetcher()->Escape(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName); + EscapeUrl(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName); str_append(aUrl, "?name=", sizeof(aUrl)); str_append(aUrl, aEscaped, sizeof(aUrl)); } - if(m_pDDNetInfoTask) - m_pDDNetInfoTask->Destroy(); - - m_pDDNetInfoTask = Fetcher()->FetchFile(aUrl, "ddnet-info.json.tmp", IStorage::TYPE_SAVE, true, true); + m_pDDNetInfoTask = std::make_shared(Storage(), aUrl, "ddnet-info.json.tmp", IStorage::TYPE_SAVE, true, true); + Engine()->AddJob(m_pDDNetInfoTask); } int CClient::GetPredictionTime() diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 493af9060..4ed9cfc30 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -3,6 +3,10 @@ #ifndef ENGINE_CLIENT_CLIENT_H #define ENGINE_CLIENT_CLIENT_H +#include + +#include "fetcher.h" + class CGraph { public: @@ -61,7 +65,6 @@ class CClient : public IClient, public CDemoPlayer::IListener IEngineMap *m_pMap; IConsole *m_pConsole; IStorage *m_pStorage; - IFetcher *m_pFetcher; IUpdater *m_pUpdater; IEngineMasterServer *m_pMasterServer; @@ -78,7 +81,6 @@ class CClient : public IClient, public CDemoPlayer::IListener class CGhostRecorder m_GhostRecorder; class CGhostLoader m_GhostLoader; class CServerBrowser m_ServerBrowser; - class CFetcher m_Fetcher; class CUpdater m_Updater; class CFriends m_Friends; class CFriends m_Foes; @@ -128,7 +130,7 @@ class CClient : public IClient, public CDemoPlayer::IListener char m_aCmdConnect[256]; // map download - IFetchTask *m_pMapdownloadTask; + std::shared_ptr m_pMapdownloadTask; char m_aMapdownloadFilename[256]; char m_aMapdownloadName[256]; IOHANDLE m_MapdownloadFile; @@ -137,7 +139,7 @@ class CClient : public IClient, public CDemoPlayer::IListener int m_MapdownloadAmount; int m_MapdownloadTotalsize; - IFetchTask *m_pDDNetInfoTask; + std::shared_ptr m_pDDNetInfoTask; // time CSmoothTime m_GameTime[2]; @@ -209,7 +211,6 @@ public: IGameClient *GameClient() { return m_pGameClient; } IEngineMasterServer *MasterServer() { return m_pMasterServer; } IStorage *Storage() { return m_pStorage; } - IFetcher *Fetcher() { return m_pFetcher; } IUpdater *Updater() { return m_pUpdater; } CClient(); @@ -302,7 +303,6 @@ public: void FinishDDNetInfo(); void LoadDDNetInfo(); - virtual IFetchTask *MapDownloadTask() { return m_pMapdownloadTask; } virtual const char *MapDownloadName() { return m_aMapdownloadName; } virtual int MapDownloadAmount() { return !m_pMapdownloadTask ? m_MapdownloadAmount : (int)m_pMapdownloadTask->Current(); } virtual int MapDownloadTotalsize() { return !m_pMapdownloadTask ? m_MapdownloadTotalsize : (int)m_pMapdownloadTask->Size(); } diff --git a/src/engine/client/fetcher.cpp b/src/engine/client/fetcher.cpp index 612892499..57aa5e962 100644 --- a/src/engine/client/fetcher.cpp +++ b/src/engine/client/fetcher.cpp @@ -10,136 +10,55 @@ #include "fetcher.h" -class CFetchTask : public IFetchTask +double CFetchTask::Current() const { return m_Current; } +double CFetchTask::Size() const { return m_Size; } +int CFetchTask::Progress() const { return m_Progress; } +int CFetchTask::State() const { return m_State; } +const char *CFetchTask::Dest() const { return m_aDest; } + +void CFetchTask::Abort() { m_Abort = true; }; + +CFetchTask::CFetchTask(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType, bool UseDDNetCA, bool CanTimeout) : + m_pStorage(pStorage), + m_StorageType(StorageType), + m_UseDDNetCA(UseDDNetCA), + m_CanTimeout(CanTimeout), + m_Size(0), + m_Progress(0), + m_State(CFetchTask::STATE_QUEUED), + m_Abort(false) { - friend class CFetcher; - class CFetcher *m_pFetcher; - - CURL *m_pHandle; - void *m_pUser; - - char m_aUrl[256]; - char m_aDest[128]; - int m_StorageType; - bool m_UseDDNetCA; - bool m_CanTimeout; - - PROGFUNC m_pfnProgressCallback; - COMPFUNC m_pfnCompCallback; - - double m_Size; - double m_Current; - int m_Progress; - int m_State; - - LOCK m_Lock; - bool m_Abort; - bool m_Destroy; - bool m_PastCB; - -public: - virtual double Current() { return m_Current; } - virtual double Size() { return m_Size; } - virtual int Progress() { return m_Progress; } - virtual int State() { return m_State; } - virtual const char *Dest() { return m_aDest; } - - virtual void Abort() { m_Abort = true; }; - virtual void Destroy(); -}; - -void CFetchTask::Destroy() -{ - lock_wait(m_Lock); - if(m_PastCB) - { - lock_destroy(m_Lock); - delete this; - } - else - { - m_Abort = true; - m_Destroy = true; - lock_unlock(m_Lock); - } + str_copy(m_aUrl, pUrl, sizeof(m_aUrl)); + str_copy(m_aDest, pDest, sizeof(m_aDest)); } -bool CFetcher::Init() + +bool FetcherInit() { - m_pStorage = Kernel()->RequestInterface(); - m_pEngine = Kernel()->RequestInterface(); - if(curl_global_init(CURL_GLOBAL_DEFAULT)) - return false; - return true; + return !curl_global_init(CURL_GLOBAL_DEFAULT); } -void CFetcher::Escape(char *pBuf, size_t size, const char *pStr) +void EscapeUrl(char *pBuf, int Size, const char *pStr) { char *pEsc = curl_easy_escape(0, pStr, 0); - str_copy(pBuf, pEsc, size); + str_copy(pBuf, pEsc, Size); curl_free(pEsc); } -void CFetcher::DestroyCallback(CJob *pJob, void *pUser) +void CFetchTask::Run() { - CFetchTask *pTask = (CFetchTask *)pUser; - - delete pJob; - - lock_wait(pTask->m_Lock); - if(pTask->m_Destroy) + CURL *pHandle = curl_easy_init(); + if(!pHandle) { - lock_destroy(pTask->m_Lock); - delete pTask; + m_State = STATE_ERROR; + return; } - else - { - pTask->m_PastCB = true; - } - lock_unlock(pTask->m_Lock); -} - -IFetchTask *CFetcher::FetchFile(const char *pUrl, const char *pDest, int StorageType, bool UseDDNetCA, bool CanTimeout, void *pUser, COMPFUNC pfnCompCb, PROGFUNC pfnProgCb) -{ - CFetchTask *pTask = new CFetchTask; - pTask->m_pFetcher = this; - - str_copy(pTask->m_aUrl, pUrl, sizeof(pTask->m_aUrl)); - str_copy(pTask->m_aDest, pDest, sizeof(pTask->m_aDest)); - pTask->m_StorageType = StorageType; - pTask->m_pUser = pUser; - pTask->m_pfnCompCallback = pfnCompCb; - pTask->m_pfnProgressCallback = pfnProgCb; - pTask->m_UseDDNetCA = UseDDNetCA; - pTask->m_CanTimeout = CanTimeout; - - pTask->m_Lock = lock_create(); - pTask->m_Abort = false; - pTask->m_Destroy = false; - pTask->m_PastCB = false; - pTask->m_Size = pTask->m_Progress = 0; - - pTask->m_State = IFetchTask::STATE_QUEUED; - - CJob *pJob = new CJob; - m_pEngine->AddJob(pJob, FetcherThread, pTask, DestroyCallback); - - return pTask; -} - -int CFetcher::FetcherThread(void *pUser) -{ - CFetchTask *pTask = (CFetchTask *)pUser; - - pTask->m_pHandle = curl_easy_init(); - if(!pTask->m_pHandle) - return 1; char aPath[512]; - if(pTask->m_StorageType == -2) - pTask->m_pFetcher->m_pStorage->GetBinaryPath(pTask->m_aDest, aPath, sizeof(aPath)); + if(m_StorageType == -2) + m_pStorage->GetBinaryPath(m_aDest, aPath, sizeof(aPath)); else - pTask->m_pFetcher->m_pStorage->GetCompletePath(pTask->m_StorageType, pTask->m_aDest, aPath, sizeof(aPath)); + m_pStorage->GetCompletePath(m_StorageType, m_aDest, aPath, sizeof(aPath)); if(fs_makedir_rec_for(aPath) < 0) dbg_msg("fetcher", "i/o error, cannot create folder for: %s", aPath); @@ -148,80 +67,76 @@ int CFetcher::FetcherThread(void *pUser) if(!File) { - dbg_msg("fetcher", "i/o error, cannot open file: %s", pTask->m_aDest); - pTask->m_State = IFetchTask::STATE_ERROR; - return 1; + dbg_msg("fetcher", "i/o error, cannot open file: %s", m_aDest); + m_State = CFetchTask::STATE_ERROR; + return; } char aErr[CURL_ERROR_SIZE]; - curl_easy_setopt(pTask->m_pHandle, CURLOPT_ERRORBUFFER, aErr); + curl_easy_setopt(pHandle, CURLOPT_ERRORBUFFER, aErr); - //curl_easy_setopt(pTask->m_pHandle, CURLOPT_VERBOSE, 1L); - if(pTask->m_CanTimeout) + //curl_easy_setopt(pHandle, CURLOPT_VERBOSE, 1L); + if(m_CanTimeout) { - curl_easy_setopt(pTask->m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, (long)g_Config.m_ClHTTPConnectTimeoutMs); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_LIMIT, (long)g_Config.m_ClHTTPLowSpeedLimit); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_TIME, (long)g_Config.m_ClHTTPLowSpeedTime); + curl_easy_setopt(pHandle, CURLOPT_CONNECTTIMEOUT_MS, (long)g_Config.m_ClHTTPConnectTimeoutMs); + curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_LIMIT, (long)g_Config.m_ClHTTPLowSpeedLimit); + curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_TIME, (long)g_Config.m_ClHTTPLowSpeedTime); } else { - curl_easy_setopt(pTask->m_pHandle, CURLOPT_CONNECTTIMEOUT_MS, 0); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_LIMIT, 0); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_LOW_SPEED_TIME, 0); + curl_easy_setopt(pHandle, CURLOPT_CONNECTTIMEOUT_MS, 0); + curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_LIMIT, 0); + curl_easy_setopt(pHandle, CURLOPT_LOW_SPEED_TIME, 0); } - curl_easy_setopt(pTask->m_pHandle, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_MAXREDIRS, 4L); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_FAILONERROR, 1L); - if(pTask->m_UseDDNetCA) + curl_easy_setopt(pHandle, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(pHandle, CURLOPT_MAXREDIRS, 4L); + curl_easy_setopt(pHandle, CURLOPT_FAILONERROR, 1L); + if(m_UseDDNetCA) { char aCAFile[512]; - pTask->m_pFetcher->m_pStorage->GetBinaryPath("data/ca-ddnet.pem", aCAFile, sizeof aCAFile); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_CAINFO, aCAFile); + m_pStorage->GetBinaryPath("data/ca-ddnet.pem", aCAFile, sizeof aCAFile); + curl_easy_setopt(pHandle, CURLOPT_CAINFO, aCAFile); } - curl_easy_setopt(pTask->m_pHandle, CURLOPT_URL, pTask->m_aUrl); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_WRITEDATA, File); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_WRITEFUNCTION, &CFetcher::WriteToFile); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_PROGRESSDATA, pTask); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_PROGRESSFUNCTION, &CFetcher::ProgressCallback); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(pTask->m_pHandle, CURLOPT_USERAGENT, "DDNet " GAME_RELEASE_VERSION " (" CONF_PLATFORM_STRING "; " CONF_ARCH_STRING ")"); + curl_easy_setopt(pHandle, CURLOPT_URL, m_aUrl); + curl_easy_setopt(pHandle, CURLOPT_WRITEDATA, File); + curl_easy_setopt(pHandle, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(pHandle, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(pHandle, CURLOPT_PROGRESSDATA, this); + curl_easy_setopt(pHandle, CURLOPT_PROGRESSFUNCTION, ProgressCallback); + curl_easy_setopt(pHandle, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(pHandle, CURLOPT_USERAGENT, "DDNet " GAME_RELEASE_VERSION " (" CONF_PLATFORM_STRING "; " CONF_ARCH_STRING ")"); - dbg_msg("fetcher", "downloading %s", pTask->m_aDest); - pTask->m_State = IFetchTask::STATE_RUNNING; - int ret = curl_easy_perform(pTask->m_pHandle); + dbg_msg("fetcher", "downloading %s", m_aDest); + m_State = CFetchTask::STATE_RUNNING; + int Ret = curl_easy_perform(pHandle); io_close(File); - if(ret != CURLE_OK) + if(Ret != CURLE_OK) { dbg_msg("fetcher", "task failed. libcurl error: %s", aErr); - pTask->m_State = (ret == CURLE_ABORTED_BY_CALLBACK) ? IFetchTask::STATE_ABORTED : IFetchTask::STATE_ERROR; + m_State = (Ret == CURLE_ABORTED_BY_CALLBACK) ? CFetchTask::STATE_ABORTED : CFetchTask::STATE_ERROR; } else { - dbg_msg("fetcher", "task done %s", pTask->m_aDest); - pTask->m_State = IFetchTask::STATE_DONE; + dbg_msg("fetcher", "task done %s", m_aDest); + m_State = CFetchTask::STATE_DONE; } - curl_easy_cleanup(pTask->m_pHandle); + curl_easy_cleanup(pHandle); - if(pTask->m_pfnCompCallback) - pTask->m_pfnCompCallback(pTask, pTask->m_pUser); - - return(ret != CURLE_OK) ? 1 : 0; + OnCompletion(); } -size_t CFetcher::WriteToFile(char *pData, size_t size, size_t nmemb, void *pFile) +size_t CFetchTask::WriteCallback(char *pData, size_t Size, size_t Number, void *pFile) { - return io_write((IOHANDLE)pFile, pData, size*nmemb); + return io_write((IOHANDLE)pFile, pData, Size * Number); } -int CFetcher::ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr) +int CFetchTask::ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr) { CFetchTask *pTask = (CFetchTask *)pUser; pTask->m_Current = DlCurr; pTask->m_Size = DlTotal; pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1); - if(pTask->m_pfnProgressCallback) - pTask->m_pfnProgressCallback(pTask, pTask->m_pUser); + pTask->OnProgress(); return pTask->m_Abort ? -1 : 0; } diff --git a/src/engine/client/fetcher.h b/src/engine/client/fetcher.h index 77319f187..99179c731 100644 --- a/src/engine/client/fetcher.h +++ b/src/engine/client/fetcher.h @@ -1,24 +1,56 @@ #ifndef ENGINE_CLIENT_FETCHER_H #define ENGINE_CLIENT_FETCHER_H -#include +#include +#include +#include -class CFetcher : public IFetcher +class CFetchTask : public IJob { private: - class IEngine *m_pEngine; - class IStorage *m_pStorage; + IStorage *m_pStorage; + + char m_aUrl[256]; + char m_aDest[128]; + int m_StorageType; + bool m_UseDDNetCA; + bool m_CanTimeout; + + double m_Size; + double m_Current; + int m_Progress; + int m_State; + + std::atomic m_Abort; + + virtual void OnProgress() { } + virtual void OnCompletion() { } + + static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr); + static size_t WriteCallback(char *pData, size_t Size, size_t Number, void *pFile); + + void Run(); public: - virtual bool Init(); + enum + { + STATE_ERROR = -1, + STATE_QUEUED, + STATE_RUNNING, + STATE_DONE, + STATE_ABORTED, + }; - virtual IFetchTask *FetchFile(const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true, void *pUser = 0, COMPFUNC pfnCompCb = 0, PROGFUNC pfnProgCb = 0); - virtual void Escape(char *pBud, size_t size, const char *pStr); + CFetchTask(IStorage *pStorage, const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true); - static void DestroyCallback(CJob *pJob, void *pUser); - static int FetcherThread(void *pUser); - static size_t WriteToFile(char *pData, size_t size, size_t nmemb, void *pFile); - static int ProgressCallback(void *pUser, double DlTotal, double DlCurr, double UlTotal, double UlCurr); + double Current() const; + double Size() const; + int Progress() const; + int State() const; + const char *Dest() const; + void Abort(); }; +bool FetcherInit(); +void EscapeUrl(char *pBud, int Size, const char *pStr); #endif diff --git a/src/engine/client/updater.cpp b/src/engine/client/updater.cpp index 55478809c..efd8c1a41 100644 --- a/src/engine/client/updater.cpp +++ b/src/engine/client/updater.cpp @@ -1,6 +1,6 @@ #include "updater.h" #include -#include +#include #include #include #include @@ -11,63 +11,128 @@ using std::string; using std::map; +class CUpdaterFetchTask : public CFetchTask +{ + char m_aBuf[256]; + char m_aBuf2[256]; + CUpdater *m_pUpdater; + + void OnCompletion(); + void OnProgress(); + +public: + CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath); +}; + +static const char *GetUpdaterUrl(char *pBuf, int BufSize, const char *pFile) +{ + str_format(pBuf, BufSize, "https://update4.ddnet.tw/%s", pFile); + return pBuf; +} + +static const char *GetUpdaterDestPath(char *pBuf, int BufSize, const char *pFile, const char *pDestPath) +{ + if(!pDestPath) + { + pDestPath = pFile; + } + str_format(pBuf, BufSize, "update/%s", pDestPath); + return pBuf; +} + +CUpdaterFetchTask::CUpdaterFetchTask(CUpdater *pUpdater, const char *pFile, const char *pDestPath) : + CFetchTask(pUpdater->m_pStorage, GetUpdaterUrl(m_aBuf, sizeof(m_aBuf), pFile), GetUpdaterDestPath(m_aBuf2, sizeof(m_aBuf), pFile, pDestPath), -2, true, false), + m_pUpdater(pUpdater) +{ +} + +void CUpdaterFetchTask::OnProgress() +{ + lock_wait(m_pUpdater->m_Lock); + str_copy(m_pUpdater->m_aStatus, Dest(), sizeof(m_pUpdater->m_aStatus)); + m_pUpdater->m_Percent = Progress(); + lock_unlock(m_pUpdater->m_Lock); +} + +void CUpdaterFetchTask::OnCompletion() +{ + const char *b = 0; + for(const char *a = Dest(); *a; a++) + if(*a == '/') + b = a + 1; + b = b ? b : Dest(); + if(!str_comp(b, "update.json")) + { + if(State() == CFetchTask::STATE_DONE) + m_pUpdater->SetCurrentState(IUpdater::GOT_MANIFEST); + else if(State() == CFetchTask::STATE_ERROR) + m_pUpdater->SetCurrentState(IUpdater::FAIL); + } + else if(!str_comp(b, m_pUpdater->m_aLastFile)) + { + if(State() == CFetchTask::STATE_DONE) + m_pUpdater->SetCurrentState(IUpdater::MOVE_FILES); + else if(State() == CFetchTask::STATE_ERROR) + m_pUpdater->SetCurrentState(IUpdater::FAIL); + } +} + CUpdater::CUpdater() { m_pClient = NULL; m_pStorage = NULL; - m_pFetcher = NULL; + m_pEngine = NULL; m_State = CLEAN; m_Percent = 0; + m_Lock = lock_create(); } void CUpdater::Init() { m_pClient = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); - m_pFetcher = Kernel()->RequestInterface(); + m_pEngine = Kernel()->RequestInterface(); m_IsWinXP = os_is_winxp_or_lower(); } -void CUpdater::ProgressCallback(IFetchTask *pTask, void *pUser) +CUpdater::~CUpdater() { - CUpdater *pUpdate = (CUpdater *)pUser; - str_copy(pUpdate->m_Status, pTask->Dest(), sizeof(pUpdate->m_Status)); - pUpdate->m_Percent = pTask->Progress(); + lock_destroy(m_Lock); } -void CUpdater::CompletionCallback(IFetchTask *pTask, void *pUser) +void CUpdater::SetCurrentState(int NewState) { - CUpdater *pUpdate = (CUpdater *)pUser; - const char *b = 0; - for(const char *a = pTask->Dest(); *a; a++) - if(*a == '/') - b = a + 1; - b = b ? b : pTask->Dest(); - if(!str_comp(b, "update.json")) - { - if(pTask->State() == IFetchTask::STATE_DONE) - pUpdate->m_State = GOT_MANIFEST; - else if(pTask->State() == IFetchTask::STATE_ERROR) - pUpdate->m_State = FAIL; - } - else if(!str_comp(b, pUpdate->m_aLastFile)) - { - if(pTask->State() == IFetchTask::STATE_DONE) - pUpdate->m_State = MOVE_FILES; - else if(pTask->State() == IFetchTask::STATE_ERROR) - pUpdate->m_State = FAIL; - } - pTask->Destroy(); + lock_wait(m_Lock); + m_State = NewState; + lock_unlock(m_Lock); +} + +int CUpdater::GetCurrentState() +{ + lock_wait(m_Lock); + int Result = m_State; + lock_unlock(m_Lock); + return Result; +} + +void CUpdater::GetCurrentFile(char *pBuf, int BufSize) +{ + lock_wait(m_Lock); + str_copy(pBuf, m_aStatus, BufSize); + lock_unlock(m_Lock); +} + +int CUpdater::GetCurrentPercent() +{ + lock_wait(m_Lock); + int Result = m_Percent; + lock_unlock(m_Lock); + return Result; } void CUpdater::FetchFile(const char *pFile, const char *pDestPath) { - char aBuf[256], aPath[256]; - str_format(aBuf, sizeof(aBuf), "https://update4.ddnet.tw/%s", pFile); - if(!pDestPath) - pDestPath = pFile; - str_format(aPath, sizeof(aPath), "update/%s", pDestPath); - m_pFetcher->FetchFile(aBuf, aPath, -2, true, false, this, &CUpdater::CompletionCallback, &CUpdater::ProgressCallback); + m_pEngine->AddJob(std::make_shared(this, pFile, pDestPath)); } void CUpdater::MoveFile(const char *pFile) @@ -93,10 +158,10 @@ void CUpdater::Update() { switch(m_State) { - case GOT_MANIFEST: + case IUpdater::GOT_MANIFEST: PerformUpdate(); break; - case MOVE_FILES: + case IUpdater::MOVE_FILES: CommitUpdate(); break; default: @@ -104,9 +169,9 @@ void CUpdater::Update() } } -void CUpdater::AddFileJob(const char *pFile, bool job) +void CUpdater::AddFileJob(const char *pFile, bool Job) { - m_FileJobs[string(pFile)] = job; + m_FileJobs[string(pFile)] = Job; } void CUpdater::ReplaceClient() diff --git a/src/engine/client/updater.h b/src/engine/client/updater.h index 8ebe176bb..0761966a7 100644 --- a/src/engine/client/updater.h +++ b/src/engine/client/updater.h @@ -2,7 +2,7 @@ #define ENGINE_CLIENT_UPDATER_H #include -#include +#include "fetcher.h" #include #include @@ -34,14 +34,18 @@ class CUpdater : public IUpdater { + friend class CUpdaterFetchTask; + class IClient *m_pClient; class IStorage *m_pStorage; - class IFetcher *m_pFetcher; + class IEngine *m_pEngine; bool m_IsWinXP; + LOCK m_Lock; + int m_State; - char m_Status[256]; + char m_aStatus[256]; int m_Percent; char m_aLastFile[256]; @@ -50,7 +54,7 @@ class CUpdater : public IUpdater std::map m_FileJobs; - void AddFileJob(const char *pFile, bool job); + void AddFileJob(const char *pFile, bool Job); void FetchFile(const char *pFile, const char *pDestPath = 0); void MoveFile(const char *pFile); @@ -61,14 +65,15 @@ class CUpdater : public IUpdater void ReplaceClient(); void ReplaceServer(); + void SetCurrentState(int NewState); + public: CUpdater(); - static void ProgressCallback(IFetchTask *pTask, void *pUser); - static void CompletionCallback(IFetchTask *pTask, void *pUser); + ~CUpdater(); - int GetCurrentState() { return m_State; }; - char *GetCurrentFile() { return m_Status; }; - int GetCurrentPercent() { return m_Percent; }; + int GetCurrentState(); + void GetCurrentFile(char *pBuf, int BufSize); + int GetCurrentPercent(); virtual void InitiateUpdate(); void Init(); diff --git a/src/engine/engine.h b/src/engine/engine.h index 11a9c3d5d..ba07f9566 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -6,10 +6,16 @@ #include "kernel.h" #include -class CHostLookup +class CHostLookup : public IJob { +private: + virtual void Run(); + public: - CJob m_Job; + CHostLookup(); + CHostLookup(const char *pHostname, int Nettype); + + int m_Result; char m_aHostname[128]; int m_Nettype; NETADDR m_Addr; @@ -25,8 +31,7 @@ protected: public: virtual void Init() = 0; virtual void InitLogfile() = 0; - virtual void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype) = 0; - virtual void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0) = 0; + virtual void AddJob(std::shared_ptr pJob) = 0; }; extern IEngine *CreateEngine(const char *pAppname, bool Silent); diff --git a/src/engine/fetcher.h b/src/engine/fetcher.h deleted file mode 100644 index d48beda66..000000000 --- a/src/engine/fetcher.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef ENGINE_FETCHER_H -#define ENGINE_FETCHER_H - -#include -#include "kernel.h" -#include "stddef.h" - -class IFetchTask -{ -public: - enum - { - STATE_ERROR = -1, - STATE_QUEUED, - STATE_RUNNING, - STATE_DONE, - STATE_ABORTED, - }; - - virtual ~IFetchTask() {}; - - virtual double Current() = 0; - virtual double Size() = 0; - virtual int Progress() = 0; - virtual int State() = 0; - virtual const char *Dest() = 0; - virtual void Abort() = 0; - - virtual void Destroy() = 0; -}; - -typedef void (*PROGFUNC)(IFetchTask *pTask, void *pUser); -typedef void (*COMPFUNC)(IFetchTask *pDest, void *pUser); - -class IFetcher : public IInterface -{ - MACRO_INTERFACE("fetcher", 0) -public: - virtual bool Init() = 0; - virtual IFetchTask *FetchFile(const char *pUrl, const char *pDest, int StorageType = -2, bool UseDDNetCA = false, bool CanTimeout = true, void *pUser = 0, COMPFUNC pfnCompCb = 0, PROGFUNC pfnProgCb = 0) = 0; - virtual void Escape(char *pBud, size_t size, const char *pStr) = 0; -}; - -#endif diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 86ca758c4..6d3f04e42 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -820,20 +820,24 @@ void CServer::InitDnsbl(int ClientID) NETADDR Addr = *m_NetServer.ClientAddr(ClientID); //TODO: support ipv6 - if (Addr.type != NETTYPE_IPV4) + if(Addr.type != NETTYPE_IPV4) return; // build dnsbl host lookup char aBuf[256]; - if (g_Config.m_SvDnsblKey[0] == '\0') + if(g_Config.m_SvDnsblKey[0] == '\0') + { // without key str_format(aBuf, sizeof(aBuf), "%d.%d.%d.%d.%s", Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost); + } else + { // with key str_format(aBuf, sizeof(aBuf), "%s.%d.%d.%d.%d.%s", g_Config.m_SvDnsblKey, Addr.ip[3], Addr.ip[2], Addr.ip[1], Addr.ip[0], g_Config.m_SvDnsblHost); + } IEngine *pEngine = Kernel()->RequestInterface(); - pEngine->HostLookup(&m_aClients[ClientID].m_DnsblLookup, aBuf, NETTYPE_IPV4); + pEngine->AddJob(m_aClients[ClientID].m_pDnsblLookup = std::make_shared(aBuf, NETTYPE_IPV4)); } int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) @@ -1843,10 +1847,10 @@ int CServer::Run() InitDnsbl(ClientID); } else if (m_aClients[ClientID].m_DnsblState == CClient::DNSBL_STATE_PENDING && - m_aClients[ClientID].m_DnsblLookup.m_Job.Status() == CJob::STATE_DONE) + m_aClients[ClientID].m_pDnsblLookup->Status() == IJob::STATE_DONE) { - if (m_aClients[ClientID].m_DnsblLookup.m_Job.Result() != 0) + if (m_aClients[ClientID].m_pDnsblLookup->m_Result != 0) { // entry not found -> whitelisted m_aClients[ClientID].m_DnsblState = CClient::DNSBL_STATE_WHITELISTED; diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 6d40b062a..433cf4f29 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -164,7 +164,7 @@ public: // DNSBL int m_DnsblState; - CHostLookup m_DnsblLookup; + std::shared_ptr m_pDnsblLookup; }; CClient m_aClients[MAX_CLIENTS]; diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index 926fb770c..f43dd59ca 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -9,11 +9,20 @@ #include #include - -static int HostLookupThread(void *pUser) +CHostLookup::CHostLookup() { - CHostLookup *pLookup = (CHostLookup *)pUser; - return net_host_lookup(pLookup->m_aHostname, &pLookup->m_Addr, pLookup->m_Nettype); +} + +CHostLookup::CHostLookup(const char *pHostname, int Nettype) +{ + str_copy(m_aHostname, pHostname, sizeof(m_aHostname)); + m_Nettype = Nettype; +} + + +void CHostLookup::Run() +{ + m_Result = net_host_lookup(m_aHostname, &m_Addr, m_Nettype); } class CEngine : public IEngine @@ -99,18 +108,11 @@ public: dbg_logger_file(g_Config.m_Logfile); } - void HostLookup(CHostLookup *pLookup, const char *pHostname, int Nettype) - { - str_copy(pLookup->m_aHostname, pHostname, sizeof(pLookup->m_aHostname)); - pLookup->m_Nettype = Nettype; - AddJob(&pLookup->m_Job, HostLookupThread, pLookup); - } - - void AddJob(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0) + void AddJob(std::shared_ptr pJob) { if(g_Config.m_Debug) dbg_msg("engine", "job added"); - m_JobPool.Add(pJob, pfnFunc, pData, pfnDestroy); + m_JobPool.Add(pJob); } }; diff --git a/src/engine/shared/jobs.cpp b/src/engine/shared/jobs.cpp index c09402886..accf338c1 100644 --- a/src/engine/shared/jobs.cpp +++ b/src/engine/shared/jobs.cpp @@ -3,6 +3,31 @@ #include #include "jobs.h" +IJob::IJob() : + m_Status(STATE_PENDING) +{ +} + +IJob::IJob(const IJob &Other) : + m_Status(STATE_PENDING) +{ +} + +IJob &IJob::operator=(const IJob &Other) +{ + m_Status = STATE_PENDING; + return *this; +} + +IJob::~IJob() +{ +} + +int IJob::Status() +{ + return m_Status.load(); +} + CJobPool::CJobPool() { // empty the pool @@ -31,7 +56,7 @@ void CJobPool::WorkerThread(void *pUser) while(!pPool->m_Shutdown) { - CJob *pJob = 0; + std::shared_ptr pJob = 0; // fetch job from queue sphore_wait(&pPool->m_Semaphore); @@ -40,9 +65,7 @@ void CJobPool::WorkerThread(void *pUser) { pJob = pPool->m_pFirstJob; pPool->m_pFirstJob = pPool->m_pFirstJob->m_pNext; - if(pPool->m_pFirstJob) - pPool->m_pFirstJob->m_pPrev = 0; - else + if(!pPool->m_pFirstJob) pPool->m_pLastJob = 0; } lock_unlock(pPool->m_Lock); @@ -50,11 +73,9 @@ void CJobPool::WorkerThread(void *pUser) // do the job if we have one if(pJob) { - pJob->m_Status = CJob::STATE_RUNNING; - pJob->m_Result = pJob->m_pfnFunc(pJob->m_pFuncData); - pJob->m_Status = CJob::STATE_DONE; - if(pJob->m_pfnDestroy) - pJob->m_pfnDestroy(pJob, pJob->m_pFuncData); + pJob->m_Status = IJob::STATE_RUNNING; + pJob->Run(); + pJob->m_Status = IJob::STATE_DONE; } } @@ -69,17 +90,11 @@ int CJobPool::Init(int NumThreads) return 0; } -int CJobPool::Add(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy) +int CJobPool::Add(std::shared_ptr pJob) { - mem_zero(pJob, sizeof(CJob)); - pJob->m_pfnFunc = pfnFunc; - pJob->m_pFuncData = pData; - pJob->m_pfnDestroy = pfnDestroy; - lock_wait(m_Lock); // add job to queue - pJob->m_pPrev = m_pLastJob; if(m_pLastJob) m_pLastJob->m_pNext = pJob; m_pLastJob = pJob; diff --git a/src/engine/shared/jobs.h b/src/engine/shared/jobs.h index 1dc30bec0..c90d09b85 100644 --- a/src/engine/shared/jobs.h +++ b/src/engine/shared/jobs.h @@ -2,31 +2,29 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #ifndef ENGINE_SHARED_JOBS_H #define ENGINE_SHARED_JOBS_H -class CJob; + +#include +#include + +class IJob; class CJobPool; -typedef int (*JOBFUNC)(void *pData); -typedef void (*CBFUNC)(CJob *pJob, void *pData); - -class CJob +class IJob { - friend class CJobPool; + friend CJobPool; - CJob *m_pPrev; - CJob *m_pNext; +private: + std::shared_ptr m_pNext; - volatile int m_Status; - volatile int m_Result; + std::atomic m_Status; + virtual void Run() = 0; - JOBFUNC m_pfnFunc; - CBFUNC m_pfnDestroy; - void *m_pFuncData; public: - CJob() - { - m_Status = STATE_DONE; - m_pFuncData = 0; - } + IJob(); + IJob(const IJob &Other); + IJob &operator=(const IJob &Other); + virtual ~IJob(); + int Status(); enum { @@ -34,9 +32,6 @@ public: STATE_RUNNING, STATE_DONE }; - - int Status() const { return m_Status; } - int Result() const { return m_Result; } }; class CJobPool @@ -51,8 +46,8 @@ class CJobPool LOCK m_Lock; SEMAPHORE m_Semaphore; - CJob *m_pFirstJob; - CJob *m_pLastJob; + std::shared_ptr m_pFirstJob; + std::shared_ptr m_pLastJob; static void WorkerThread(void *pUser); @@ -61,6 +56,6 @@ public: ~CJobPool(); int Init(int NumThreads); - int Add(CJob *pJob, JOBFUNC pfnFunc, void *pData, CBFUNC pfnDestroy = 0); + int Add(std::shared_ptr pJob); }; #endif diff --git a/src/engine/shared/masterserver.cpp b/src/engine/shared/masterserver.cpp index 1968da30c..85d1f3f15 100644 --- a/src/engine/shared/masterserver.cpp +++ b/src/engine/shared/masterserver.cpp @@ -20,7 +20,7 @@ public: NETADDR m_Addr; bool m_Valid; int m_Count; - CHostLookup m_Lookup; + std::shared_ptr m_pLookup; }; enum @@ -53,11 +53,10 @@ public: // add lookup jobs for(int i = 0; i < MAX_MASTERSERVERS; i++) { - m_pEngine->HostLookup(&m_aMasterServers[i].m_Lookup, m_aMasterServers[i].m_aHostname, Nettype); + *m_aMasterServers[i].m_pLookup = CHostLookup(m_aMasterServers[i].m_aHostname, Nettype); + m_pEngine->AddJob(m_aMasterServers[i].m_pLookup); m_aMasterServers[i].m_Valid = false; m_aMasterServers[i].m_Count = 0; - - //dbg_msg("MasterServer", "Lookup id: %d, name: %s, nettype: %d", i, m_aMasterServers[i].m_aHostname, Nettype); } m_State = STATE_UPDATE; @@ -73,23 +72,19 @@ public: for(int i = 0; i < MAX_MASTERSERVERS; i++) { - if(m_aMasterServers[i].m_Lookup.m_Job.Status() != CJob::STATE_DONE) + if(m_aMasterServers[i].m_pLookup->Status() != IJob::STATE_DONE) m_State = STATE_UPDATE; else { - if(m_aMasterServers[i].m_Lookup.m_Job.Result() == 0) + if(m_aMasterServers[i].m_pLookup->m_Result == 0) { - m_aMasterServers[i].m_Addr = m_aMasterServers[i].m_Lookup.m_Addr; + m_aMasterServers[i].m_Addr = m_aMasterServers[i].m_pLookup->m_Addr; m_aMasterServers[i].m_Addr.port = 8300; m_aMasterServers[i].m_Valid = true; - - //dbg_msg("MasterServer", "Set server %d, name: %s with addr-port: %d addr-ip %s addr-type %d", i, m_aMasterServers[i].m_aHostname, m_aMasterServers[i].m_Addr.port, m_aMasterServers[i].m_Addr.ip, m_aMasterServers[i].m_Addr.type); } else { m_aMasterServers[i].m_Valid = false; - - // dbg_msg("MasterServer", "Dropped %d, name: %s with addr-port: %d addr-ip %s addr-type %d", i, m_aMasterServers[i].m_aHostname); } } } diff --git a/src/engine/updater.h b/src/engine/updater.h index 2f3d3ec1f..0173628e6 100644 --- a/src/engine/updater.h +++ b/src/engine/updater.h @@ -23,7 +23,7 @@ public: virtual void InitiateUpdate() = 0; virtual int GetCurrentState() = 0; - virtual char *GetCurrentFile() = 0; + virtual void GetCurrentFile(char *pBuf, int BufSize) = 0; virtual int GetCurrentPercent() = 0; }; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 00904b089..3876c604b 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1321,9 +1321,15 @@ void CMenus::RenderServerbrowser(CUIRect MainView) TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f); } else if(State == IUpdater::CLEAN) + { str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION); + } else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART) - str_format(aBuf, sizeof(aBuf), "Downloading %s:", Updater()->GetCurrentFile()); + { + char aCurrentFile[64]; + Updater()->GetCurrentFile(aCurrentFile, sizeof(aCurrentFile)); + str_format(aBuf, sizeof(aBuf), "Downloading %s:", aCurrentFile); + } else if(State == IUpdater::FAIL) { str_format(aBuf, sizeof(aBuf), "Failed to download a file! Restart client to retry..."); diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 7fdb5e25a..53eb27533 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -13,29 +13,25 @@ #include "sounds.h" -struct CUserData +CSoundLoading::CSoundLoading(CGameClient *pGameClient, bool Render) : + m_pGameClient(pGameClient), + m_Render(Render) { - CGameClient *m_pGameClient; - bool m_Render; -} g_UserData; +} -static int LoadSoundsThread(void *pUser) +void CSoundLoading::Run() { - CUserData *pData = static_cast(pUser); - for(int s = 0; s < g_pData->m_NumSounds; s++) { for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++) { - int Id = pData->m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename); + int Id = m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename); g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id; } - if(pData->m_Render) - pData->m_pGameClient->m_pMenus->RenderLoading(); + if(m_Render) + m_pGameClient->m_pMenus->RenderLoading(); } - - return 0; } int CSounds::GetSampleId(int SetId) @@ -79,16 +75,13 @@ void CSounds::OnInit() // load sounds if(g_Config.m_ClThreadsoundloading) { - g_UserData.m_pGameClient = m_pClient; - g_UserData.m_Render = false; - m_pClient->Engine()->AddJob(&m_SoundJob, LoadSoundsThread, &g_UserData); + m_pSoundJob = std::make_shared(m_pClient, false); + m_pClient->Engine()->AddJob(m_pSoundJob); m_WaitForSoundJob = true; } else { - g_UserData.m_pGameClient = m_pClient; - g_UserData.m_Render = true; - LoadSoundsThread(&g_UserData); + CSoundLoading(m_pClient, true).Run(); m_WaitForSoundJob = false; } } @@ -113,7 +106,7 @@ void CSounds::OnRender() // check for sound initialisation if(m_WaitForSoundJob) { - if(m_SoundJob.Status() == CJob::STATE_DONE) + if(m_pSoundJob->Status() == IJob::STATE_DONE) m_WaitForSoundJob = false; else return; diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index b8f7a8657..ecc988bce 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -2,9 +2,20 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #ifndef GAME_CLIENT_COMPONENTS_SOUNDS_H #define GAME_CLIENT_COMPONENTS_SOUNDS_H +#include #include #include +class CSoundLoading : public IJob +{ + CGameClient *m_pGameClient; + bool m_Render; + +public: + CSoundLoading(CGameClient *pGameClient, bool Render); + void Run(); +}; + class CSounds : public CComponent { enum @@ -18,7 +29,7 @@ class CSounds : public CComponent } m_aQueue[QUEUE_SIZE]; int m_QueuePos; int64 m_QueueWaitTime; - class CJob m_SoundJob; + std::shared_ptr m_pSoundJob; bool m_WaitForSoundJob; int GetSampleId(int SetId); diff --git a/src/game/server/score.h b/src/game/server/score.h index 8b590fd63..9f7cf9c4f 100644 --- a/src/game/server/score.h +++ b/src/game/server/score.h @@ -43,13 +43,13 @@ public: CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; } - virtual void MapInfo(int ClientID, const char* MapName) = 0; - virtual void MapVote(int ClientID, const char* MapName) = 0; + virtual void MapInfo(int ClientID, const char *pMapName) = 0; + virtual void MapVote(int ClientID, const char *pMapName) = 0; virtual void CheckBirthday(int ClientID) = 0; virtual void LoadScore(int ClientID) = 0; - virtual void SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS]) = 0; + virtual void SaveScore(int ClientID, float Time, float aCpTime[NUM_CHECKPOINTS]) = 0; - virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time) = 0; + virtual void SaveTeamScore(int *pClientIDs, unsigned int Size, float Time) = 0; virtual void ShowTop5(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0; virtual void ShowRank(int ClientID, const char *pName, bool Search=false) = 0; @@ -60,8 +60,8 @@ public: virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0; virtual void ShowPoints(int ClientID, const char *pName, bool Search=false) = 0; - virtual void RandomMap(int ClientID, int stars) = 0; - virtual void RandomUnfinishedMap(int ClientID, int stars) = 0; + virtual void RandomMap(int ClientID, int Stars) = 0; + virtual void RandomUnfinishedMap(int ClientID, int Stars) = 0; virtual void SaveTeam(int Team, const char *pCode, int ClientID, const char *pServer) = 0; virtual void LoadTeam(const char *pCode, int ClientID) = 0;