pthread -> std::thread (5/7) - Replace sdl semaphore with condition variable
This removes a dependency on the SDL_Thread header. Differential Revision: https://code.wildfiregames.com/D1921 This was SVN commit r22772.
This commit is contained in:
parent
b429d0ce03
commit
62dd922bc0
@ -284,12 +284,6 @@ CTextureConverter::CTextureConverter(PIVFS vfs, bool highQuality) :
|
||||
ENSURE(nvtt::version() >= NVTT_VERSION);
|
||||
#endif
|
||||
|
||||
// Set up the worker thread:
|
||||
|
||||
// Use SDL semaphores since OS X doesn't implement sem_init
|
||||
m_WorkerSem = SDL_CreateSemaphore(0);
|
||||
ENSURE(m_WorkerSem);
|
||||
|
||||
m_WorkerThread = std::thread(RunThread, this);
|
||||
|
||||
// Maybe we should share some centralised pool of worker threads?
|
||||
@ -304,14 +298,19 @@ CTextureConverter::~CTextureConverter()
|
||||
m_Shutdown = true;
|
||||
}
|
||||
|
||||
// Wake it up so it sees the notification
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
while (true)
|
||||
{
|
||||
// Wake the thread up so that it shutdowns.
|
||||
// If we send the message once, there is a chance it will be missed,
|
||||
// so keep sending until shtudown becomes false again, indicating that the thread has shut down.
|
||||
std::lock_guard<std::mutex> lock(m_WorkerMutex);
|
||||
m_WorkerCV.notify_all();
|
||||
if (!m_Shutdown)
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for it to shut down cleanly
|
||||
m_WorkerThread.join();
|
||||
|
||||
// Clean up resources
|
||||
SDL_DestroySemaphore(m_WorkerSem);
|
||||
}
|
||||
|
||||
bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath& src, const VfsPath& dest, const Settings& settings)
|
||||
@ -463,7 +462,7 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath
|
||||
}
|
||||
|
||||
// Wake up the worker thread
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
m_WorkerCV.notify_all();
|
||||
|
||||
return true;
|
||||
|
||||
@ -527,9 +526,7 @@ bool CTextureConverter::Poll(CTexturePtr& texture, VfsPath& dest, bool& ok)
|
||||
bool CTextureConverter::IsBusy()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_WorkerMutex);
|
||||
bool busy = !m_RequestQueue.empty();
|
||||
|
||||
return busy;
|
||||
return !m_RequestQueue.empty();
|
||||
}
|
||||
|
||||
void CTextureConverter::RunThread(CTextureConverter* textureConverter)
|
||||
@ -540,15 +537,22 @@ void CTextureConverter::RunThread(CTextureConverter* textureConverter)
|
||||
#if CONFIG2_NVTT
|
||||
|
||||
// Wait until the main thread wakes us up
|
||||
while (SDL_SemWait(textureConverter->m_WorkerSem) == 0)
|
||||
while (true)
|
||||
{
|
||||
// We may have several textures in the incoming queue, process them all before going back to sleep.
|
||||
if (!textureConverter->IsBusy()) {
|
||||
std::unique_lock<std::mutex> wait_lock(textureConverter->m_WorkerMutex);
|
||||
// Use the no-condition variant because spurious wake-ups don't matter that much here.
|
||||
textureConverter->m_WorkerCV.wait(wait_lock);
|
||||
}
|
||||
|
||||
g_Profiler2.RecordSyncMarker();
|
||||
PROFILE2_EVENT("wakeup");
|
||||
|
||||
shared_ptr<ConversionRequest> request;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(textureConverter->m_WorkerMutex);
|
||||
std::lock_guard<std::mutex> wait_lock(textureConverter->m_WorkerMutex);
|
||||
if (textureConverter->m_Shutdown)
|
||||
break;
|
||||
// If we weren't woken up for shutdown, we must have been woken up for
|
||||
@ -588,9 +592,11 @@ void CTextureConverter::RunThread(CTextureConverter* textureConverter)
|
||||
result->output.buffer[80] &= ~0x40; // DDPF_RGB in DDS_PIXELFORMAT.dwFlags
|
||||
|
||||
// Push the result onto the queue
|
||||
std::lock_guard<std::mutex> lock(textureConverter->m_WorkerMutex);
|
||||
std::lock_guard<std::mutex> wait_lock(textureConverter->m_WorkerMutex);
|
||||
textureConverter->m_ResultQueue.push_back(result);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> wait_lock(textureConverter->m_WorkerMutex);
|
||||
textureConverter->m_Shutdown = false;
|
||||
#endif
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
#define INCLUDED_TEXTURECONVERTER
|
||||
|
||||
#include "lib/file/vfs/vfs.h"
|
||||
#include "lib/external_libraries/libsdl.h"
|
||||
|
||||
#include "TextureManager.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
@ -208,7 +208,7 @@ private:
|
||||
|
||||
std::thread m_WorkerThread;
|
||||
std::mutex m_WorkerMutex;
|
||||
SDL_sem* m_WorkerSem;
|
||||
std::condition_variable m_WorkerCV;
|
||||
|
||||
struct ConversionRequest;
|
||||
struct ConversionResult;
|
||||
|
@ -341,8 +341,7 @@ public:
|
||||
if (m_TextureConverter.Poll(textureOut, dest, ok))
|
||||
return ok;
|
||||
|
||||
// Spin-loop is dumb but it works okay for now
|
||||
SDL_Delay(0);
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#if HAVE_PCH
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#endif // HAVE_PCH
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "lib/timer.h"
|
||||
#include "lib/utf8.h"
|
||||
#include "lib/external_libraries/curl.h"
|
||||
#include "lib/external_libraries/libsdl.h"
|
||||
#include "lib/external_libraries/zlib.h"
|
||||
#include "lib/file/archive/stream.h"
|
||||
#include "lib/os_path.h"
|
||||
@ -31,6 +30,7 @@
|
||||
#include "ps/Filesystem.h"
|
||||
#include "ps/Profiler2.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@ -136,22 +136,11 @@ public:
|
||||
m_Headers = curl_slist_append(m_Headers, "Accept: ");
|
||||
curl_easy_setopt(m_Curl, CURLOPT_HTTPHEADER, m_Headers);
|
||||
|
||||
|
||||
// Set up the worker thread:
|
||||
|
||||
// Use SDL semaphores since OS X doesn't implement sem_init
|
||||
m_WorkerSem = SDL_CreateSemaphore(0);
|
||||
ENSURE(m_WorkerSem);
|
||||
|
||||
m_WorkerThread = std::thread(RunThread, this);
|
||||
}
|
||||
|
||||
~CUserReporterWorker()
|
||||
{
|
||||
// Clean up resources
|
||||
|
||||
SDL_DestroySemaphore(m_WorkerSem);
|
||||
|
||||
curl_slist_free_all(m_Headers);
|
||||
curl_easy_cleanup(m_Curl);
|
||||
}
|
||||
@ -167,7 +156,7 @@ public:
|
||||
m_Enabled = enabled;
|
||||
|
||||
// Wake up the worker thread
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
m_WorkerCV.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +175,7 @@ public:
|
||||
}
|
||||
|
||||
// Wake up the worker thread
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
m_WorkerCV.notify_all();
|
||||
|
||||
// Wait for it to shut down cleanly
|
||||
// TODO: should have a timeout in case of network hangs
|
||||
@ -215,7 +204,7 @@ public:
|
||||
}
|
||||
|
||||
// Wake up the worker thread
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
m_WorkerCV.notify_all();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,7 +217,7 @@ public:
|
||||
if (now > m_LastUpdateTime + TIMER_CHECK_INTERVAL)
|
||||
{
|
||||
// Wake up the worker thread
|
||||
SDL_SemPost(m_WorkerSem);
|
||||
m_WorkerCV.notify_all();
|
||||
|
||||
m_LastUpdateTime = now;
|
||||
}
|
||||
@ -259,7 +248,7 @@ private:
|
||||
SetStatus("waiting");
|
||||
|
||||
/*
|
||||
* We use a semaphore to let the thread be woken up when it has
|
||||
* We use a condition_variable to let the thread be woken up when it has
|
||||
* work to do. Various actions from the main thread can wake it:
|
||||
* * SetEnabled()
|
||||
* * Shutdown()
|
||||
@ -271,19 +260,17 @@ private:
|
||||
* nothing during the subsequent wakeups). We should never hang due to
|
||||
* processing fewer actions than wakeups.
|
||||
*
|
||||
* Retransmission timeouts are triggered via the main thread - we can't simply
|
||||
* use SDL_SemWaitTimeout because on Linux it's implemented as an inefficient
|
||||
* busy-wait loop, and we can't use a manual busy-wait with a long delay time
|
||||
* because we'd lose responsiveness. So the main thread pings the worker
|
||||
* occasionally so it can check its timer.
|
||||
* Retransmission timeouts are triggered via the main thread.
|
||||
*/
|
||||
|
||||
// Wait until the main thread wakes us up
|
||||
while (true)
|
||||
{
|
||||
g_Profiler2.RecordRegionEnter("semaphore wait");
|
||||
g_Profiler2.RecordRegionEnter("condition_variable wait");
|
||||
|
||||
ENSURE(SDL_SemWait(m_WorkerSem) == 0);
|
||||
std::unique_lock<std::mutex> lock(m_WorkerMutex);
|
||||
m_WorkerCV.wait(lock, [this] { return m_Enabled || m_Shutdown; });
|
||||
lock.unlock();
|
||||
|
||||
g_Profiler2.RecordRegionLeave();
|
||||
|
||||
@ -488,7 +475,7 @@ private:
|
||||
// Thread-related members:
|
||||
std::thread m_WorkerThread;
|
||||
std::mutex m_WorkerMutex;
|
||||
SDL_sem* m_WorkerSem;
|
||||
std::condition_variable m_WorkerCV;
|
||||
|
||||
// Shared by main thread and worker thread:
|
||||
// These variables are all protected by m_WorkerMutex
|
||||
|
Loading…
Reference in New Issue
Block a user