#include "C4JThread.h" std::vector C4JThread::ms_threadList; std::mutex C4JThread::ms_threadListMutex; thread_local C4JThread* C4JThread::tls_currentThread = nullptr; C4JThread C4JThread::m_mainThread("MainThread"); C4JThread::Event::Event(EMode mode) : m_mode(mode) { } void C4JThread::Event::Set() { std::lock_guard lock(m_mutex); m_signaled = true; m_cv.notify_all(); } void C4JThread::Event::Clear() { std::lock_guard lock(m_mutex); m_signaled = false; } unsigned long C4JThread::Event::WaitForSignal(int timeoutMs) { std::unique_lock lock(m_mutex); if (timeoutMs < 0) { m_cv.wait(lock, [&] { return m_signaled; }); } else { if (!m_cv.wait_for(lock, std::chrono::milliseconds(timeoutMs), [&] { return m_signaled; })) return 0x102; } if (m_mode == e_modeAutoClear) m_signaled = false; return 0; } C4JThread::EventArray::EventArray(int size, Event::EMode mode) { m_events.reserve(size); for (int i = 0; i < size; ++i) m_events.emplace_back(mode); } void C4JThread::EventArray::Set(int i) { m_events[i].Set(); } void C4JThread::EventArray::Clear(int i) { m_events[i].Clear(); } void C4JThread::EventArray::SetAll() { for (auto& e : m_events) e.Set(); } void C4JThread::EventArray::ClearAll() { for (auto& e : m_events) e.Clear(); } unsigned long C4JThread::EventArray::WaitForSingle(int index, int timeoutMs) { return m_events[index].WaitForSignal(timeoutMs); } unsigned long C4JThread::EventArray::WaitForAll(int timeoutMs) { for (auto& e : m_events) e.WaitForSignal(timeoutMs); return 0; } unsigned long C4JThread::EventArray::WaitForAny(int timeoutMs) { while (true) { for (auto& e : m_events) { if (e.WaitForSignal(0) == 0) return 0; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } C4JThread::C4JThread(C4JThreadStartFunc* startFunc, void* param, const char* name, int) : m_threadParam(param), m_startFunc(startFunc) { std::strncpy(m_threadName, name, sizeof(m_threadName)); std::lock_guard lock(ms_threadListMutex); ms_threadList.push_back(this); } C4JThread::C4JThread(const char* mainThreadName) { std::strncpy(m_threadName, mainThreadName, sizeof(m_threadName)); tls_currentThread = this; m_isRunning = true; m_hasStarted = true; } C4JThread::~C4JThread() { if (m_thread.joinable()) m_thread.join(); } void C4JThread::threadEntry() { tls_currentThread = this; m_isRunning = true; m_exitCode = (*m_startFunc)(m_threadParam); m_isRunning = false; } void C4JThread::Run() { m_hasStarted = true; m_thread = std::thread(&C4JThread::threadEntry, this); } unsigned long C4JThread::WaitForCompletion(int) { if (m_thread.joinable()) m_thread.join(); return 0; } void C4JThread::Sleep(int ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } C4JThread* C4JThread::getCurrentThread() { return tls_currentThread ? tls_currentThread : &m_mainThread; } bool C4JThread::isMainThread() { return getCurrentThread() == &m_mainThread; }