161 lines
3.2 KiB
C++
161 lines
3.2 KiB
C++
#include "C4JThread.h"
|
|
|
|
std::vector<C4JThread*> C4JThread::ms_threadList;
|
|
ThreadLock C4JThread::ms_threadListLock;
|
|
|
|
thread_local C4JThread* C4JThread::tls_currentThread = nullptr;
|
|
C4JThread C4JThread::m_mainThread("MainThread");
|
|
|
|
C4JThread::Event::Event(EMode mode)
|
|
: m_mode(mode)
|
|
{
|
|
}
|
|
|
|
void C4JThread::Event::Set()
|
|
{
|
|
m_lock.lock();
|
|
m_signaled = true;
|
|
m_cv.notify_all();
|
|
m_lock.unlock();
|
|
}
|
|
|
|
void C4JThread::Event::Clear()
|
|
{
|
|
m_lock.lock();
|
|
m_signaled = false;
|
|
m_lock.unlock();
|
|
}
|
|
|
|
unsigned long C4JThread::Event::WaitForSignal(int timeoutMs)
|
|
{
|
|
m_lock.lock();
|
|
|
|
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;
|
|
|
|
m_lock.unlock();
|
|
return 0;
|
|
}
|
|
|
|
C4JThread::EventArray::EventArray(int size, Event::EMode mode)
|
|
{
|
|
m_events.reserve(size);
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
m_events.push_back(std::unique_ptr<Event>(new Event(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));
|
|
ms_threadListLock.lock();
|
|
ms_threadList.push_back(this);
|
|
ms_threadListLock.unlock();
|
|
}
|
|
|
|
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;
|
|
} |