최종완료보고 버전
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
|
||||
#ifndef THREAD__H_
|
||||
#define THREAD__H_
|
||||
|
||||
|
||||
#ifndef COMMON__H_
|
||||
#include "common.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#pragma once
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
//#include <signal.h>
|
||||
|
||||
//#define WAIT_NEW_VER_
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define pthread_self GetCurrentThreadId
|
||||
#else
|
||||
#define GetCurrentThreadId pthread_self
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
class HSyncObject : public HObject
|
||||
{
|
||||
public:
|
||||
HSyncObject()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
InitializeCriticalSection(&m_instance);
|
||||
#else
|
||||
pthread_mutex_init(&m_instance, NULL);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
virtual ~HSyncObject()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DeleteCriticalSection(&m_instance);
|
||||
#else
|
||||
pthread_mutex_destroy(&m_instance);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
bool IsLocked();
|
||||
|
||||
int Lock();
|
||||
int Unlock();
|
||||
|
||||
protected:
|
||||
#ifdef _WIN32
|
||||
CRITICAL_SECTION m_instance;
|
||||
#else
|
||||
pthread_mutex_t m_instance;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline int HSyncObject::Lock()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
EnterCriticalSection(&m_instance);
|
||||
return 0;
|
||||
#else
|
||||
return pthread_mutex_lock(&m_instance);
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
inline int HSyncObject::Unlock()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LeaveCriticalSection(&m_instance);
|
||||
return 0;
|
||||
#else
|
||||
return pthread_mutex_unlock(&m_instance);
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
class HAutoLock : public HObject
|
||||
{
|
||||
public:
|
||||
HAutoLock(HSyncObject * pObject) : m_pObject(pObject) { m_pObject->Lock(); }
|
||||
~HAutoLock() { m_pObject->Unlock(); }
|
||||
|
||||
private:
|
||||
HSyncObject * m_pObject;
|
||||
};
|
||||
|
||||
|
||||
class HSyncEvent : public HObject
|
||||
{
|
||||
public:
|
||||
HSyncEvent(bool bManualReset = false, bool bInitialState = false)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_hEvent = CreateEvent(NULL, bManualReset, bInitialState, NULL);
|
||||
#else
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
pthread_cond_init(&m_cond, NULL);
|
||||
|
||||
m_bManualReset = bManualReset;
|
||||
|
||||
if (bInitialState)
|
||||
m_bEventSet = true;
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
~HSyncEvent()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(m_hEvent);
|
||||
#else
|
||||
pthread_cond_destroy(&m_cond);
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
bool SetEvent()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::SetEvent(m_hEvent) != false;
|
||||
#else
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
m_bEventSet = true;
|
||||
pthread_cond_signal(&m_cond);
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
#endif // _WIN32
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResetEvent()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::ResetEvent(m_hEvent) != false;
|
||||
#else
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
m_bEventSet = false;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
#endif // _WIN32
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wait(DWORD dwWaitTime) // dwTimeout : msec
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (WaitForSingleObject(m_hEvent, dwWaitTime) == WAIT_TIMEOUT)
|
||||
return false;
|
||||
#else
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
|
||||
return true;
|
||||
|
||||
ts.tv_sec += dwWaitTime / 1000; // seconds
|
||||
ts.tv_nsec += (dwWaitTime % 1000) * 1000000; // nanoseconds
|
||||
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
if (m_bEventSet)
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
if (m_bManualReset == false)
|
||||
m_bEventSet = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int nResult = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
|
||||
if (nResult == ETIMEDOUT)
|
||||
return false;
|
||||
|
||||
if (m_bManualReset == false)
|
||||
m_bEventSet = false;
|
||||
#endif // _WIN32
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HANDLE m_hEvent;
|
||||
#else
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
|
||||
bool m_bManualReset;
|
||||
volatile bool m_bEventSet;
|
||||
#endif // _WIN32
|
||||
};
|
||||
|
||||
|
||||
class HThread : public HObject
|
||||
{
|
||||
public:
|
||||
HThread(bool bAutoDelete = false, size_t nStackSize = 0)
|
||||
: m_bAutoDelete(bAutoDelete)
|
||||
, m_nStackSize(nStackSize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_hThread = NULL;
|
||||
#else
|
||||
m_tId = 0;
|
||||
|
||||
#ifndef WAIT_NEW_VER_
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
pthread_cond_init(&m_cond, NULL);
|
||||
#endif
|
||||
#endif // WIN32
|
||||
}
|
||||
~HThread() {}
|
||||
|
||||
#ifdef _WIN32
|
||||
inline HANDLE GetThreadId() { return m_hThread; }
|
||||
#else
|
||||
inline pthread_t GetThreadId() { return m_tId; }
|
||||
#endif
|
||||
|
||||
|
||||
virtual inline unsigned long Begin();
|
||||
|
||||
bool WaitForTermination(DWORD dwWaitTime)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_hThread == NULL)
|
||||
return true;
|
||||
|
||||
if (WaitForSingleObject(m_hThread, dwWaitTime) == WAIT_TIMEOUT)
|
||||
return false;
|
||||
#else
|
||||
if (m_tId == 0)
|
||||
return true;
|
||||
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
|
||||
return true;
|
||||
|
||||
ts.tv_sec += dwWaitTime / 1000; // seconds
|
||||
ts.tv_nsec += (dwWaitTime % 1000) * 1000000; // nanoseconds
|
||||
|
||||
#ifndef WAIT_NEW_VER_
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
int nResult = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
|
||||
if (nResult == ETIMEDOUT)
|
||||
return false;
|
||||
#else
|
||||
if (pthread_timedjoin_np(m_tId, NULL, &ts) == ETIMEDOUT)
|
||||
return false;
|
||||
#endif // WAIT_NEW_VER_
|
||||
#endif // WIN32
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(ANDROID)
|
||||
void TerminateThread(DWORD dwExitCode = 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_hThread == NULL)
|
||||
return;
|
||||
|
||||
::TerminateThread(m_hThread, dwExitCode);
|
||||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
#else
|
||||
if (m_tId == 0)
|
||||
return;
|
||||
|
||||
pthread_cancel(m_tId);
|
||||
m_tId = 0;
|
||||
#endif
|
||||
}
|
||||
#endif //
|
||||
|
||||
protected:
|
||||
virtual void Main() = 0;
|
||||
virtual void OnTerminated() {}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
inline static DWORD WINAPI
|
||||
#else
|
||||
inline static void *
|
||||
#endif
|
||||
BeginThread(void * lpParameter);
|
||||
|
||||
private:
|
||||
void MainCallBack();
|
||||
|
||||
private:
|
||||
bool m_bAutoDelete;
|
||||
size_t m_nStackSize; // bytes
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE m_hThread;
|
||||
#else
|
||||
pthread_t m_tId;
|
||||
|
||||
#ifndef WAIT_NEW_VER_
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
inline unsigned long HThread::Begin()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD dwThreadId;
|
||||
if ((m_hThread = ::CreateThread(NULL, m_nStackSize, BeginThread, this, 0, &dwThreadId)) == NULL)
|
||||
return ::GetLastError();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
if (m_nStackSize > 0)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, m_nStackSize);
|
||||
#if 0 // do not use
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
#endif
|
||||
int nResult = pthread_create(&m_tId, &attr, BeginThread, (void *)this);
|
||||
pthread_attr_destroy(&attr);
|
||||
return nResult;
|
||||
}
|
||||
|
||||
return pthread_create(&m_tId, NULL, BeginThread, (void *)this);
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
inline DWORD WINAPI
|
||||
#else
|
||||
inline void *
|
||||
#endif
|
||||
HThread::BeginThread(void * lpParameter)
|
||||
{
|
||||
((HThread *)lpParameter)->MainCallBack();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline void HThread::MainCallBack()
|
||||
{
|
||||
Main();
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef WAIT_NEW_VER_
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
pthread_cond_broadcast(&m_cond);
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
#endif // WAIT_NEW_VER_
|
||||
|
||||
pthread_detach(m_tId);
|
||||
#endif
|
||||
|
||||
OnTerminated();
|
||||
|
||||
if (m_bAutoDelete)
|
||||
delete this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
|
||||
class HThreadExecuter : public HThread
|
||||
{
|
||||
public:
|
||||
HThreadExecuter()
|
||||
{
|
||||
m_fnThreadMainCallBack = NULL;
|
||||
m_pThreadMainParam = NULL;
|
||||
m_fnExitThreadCallBack = NULL;
|
||||
m_pOnExitThreadParam = NULL;
|
||||
}
|
||||
HThreadExecuter(bool bAutoDelete, size_t nStackSize) : HThread(bAutoDelete, nStackSize)
|
||||
{
|
||||
m_fnThreadMainCallBack = NULL;
|
||||
m_pThreadMainParam = NULL;
|
||||
m_fnExitThreadCallBack = NULL;
|
||||
m_pOnExitThreadParam = NULL;
|
||||
}
|
||||
~HThreadExecuter()
|
||||
{
|
||||
m_fnThreadMainCallBack = NULL;
|
||||
m_pThreadMainParam = NULL;
|
||||
m_fnExitThreadCallBack = NULL;
|
||||
m_pOnExitThreadParam = NULL;
|
||||
}
|
||||
|
||||
inline void Initialize(void (*fnThreadMainCallBack)(void * pThreadParameter), // thread main procedure
|
||||
void * pThreadMainParam, // parmeter for thread main
|
||||
void (*fnExitThreadCallBack)(void * pThreadParameter), // terminated thread call back
|
||||
void * pOnExitThreadParam) // parmeter for terminated thread
|
||||
{
|
||||
m_fnThreadMainCallBack = fnThreadMainCallBack;
|
||||
m_pThreadMainParam = pThreadMainParam;
|
||||
m_fnExitThreadCallBack = fnExitThreadCallBack;
|
||||
m_pOnExitThreadParam = pOnExitThreadParam;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void Main()
|
||||
{
|
||||
if (m_fnThreadMainCallBack)
|
||||
m_fnThreadMainCallBack(m_pThreadMainParam);
|
||||
}
|
||||
|
||||
inline void OnTerminated()
|
||||
{
|
||||
if (m_fnExitThreadCallBack)
|
||||
m_fnExitThreadCallBack(m_pOnExitThreadParam);
|
||||
}
|
||||
|
||||
protected:
|
||||
void (*m_fnThreadMainCallBack)(void * pThreadParameter);
|
||||
void * m_pThreadMainParam;
|
||||
|
||||
void (*m_fnExitThreadCallBack)(void * pThreadParameter);
|
||||
void * m_pOnExitThreadParam;
|
||||
};
|
||||
/*
|
||||
<below add to .h file>
|
||||
protected:
|
||||
// $(Name) thread part
|
||||
static inline void $(Name)ThreadCallBack(void * pParam) { return static_cast<$(ClassName) *>(pParam)->$(Name)ThreadMain(); }
|
||||
static inline void $(Name)ThreadTerminatedCallBack(void * pParam) { static_cast<$(ClassName) *>(pParam)->On$(Name)ThreadTerminated(); }
|
||||
|
||||
void $(Name)ThreadMain();
|
||||
void On$(Name)ThreadTerminated();
|
||||
|
||||
HThreadExecuter * m_p$(Name)Thread;
|
||||
//
|
||||
|
||||
|
||||
<add to constructor>
|
||||
m_p$(Name)Thread = new HThreadExecuter();
|
||||
m_p$(Name)Thread->Initialize($(Name)ThreadCallBack, this, $(Name)ThreadTerminatedCallBack, this);
|
||||
m_p$(Name)Thread->Begin();
|
||||
|
||||
<add to destructor or termination code>
|
||||
delete m_p$(Name)Thread;
|
||||
*/
|
||||
#endif // THREAD__H_
|
||||
Reference in New Issue
Block a user