/*
* @note :同步事件/信号量/互斥/临界区/线程/线程池实现(win32/linux),不支持unicode
* @author :Andy.Ro
* @email :Qwuloo@qq.com
*/
#ifndef _XTHREAD_H_INCLUDE_
#define _XTHREAD_H_INCLUDE_
#ifdef WIN32
#include <Windows.h>
#include <process.h>
#else
// linux 手测参考:http://www.mkssoftware.com/docs
#include <sched.h>
#include <pthread.h>
#include <semaphore.h> // POSIX信号量(用户态)
//#include <sys/sem.h> // SYSTEM V信号量(用户态)
#include <sys/types.h>
#include <unistd.h>
#define INFINITE 0xFFFFFFFF
#endif
#include "../Interface/xTypes.h"
#ifdef WIN32
typedef u32_t pthread_t;
#endif
namespace ESMT {
class xSyncObject;
class xEvent; // 事件内核对象
class xSemaphore; // 信号量内核对象:linux 下仅实现了POSIX信号量
class xMutex; // 互斥内核对象
class xSection; // 临界区用户对象
class xThread; // 线程类
class xThreadPool; // 线程池
//------------------------------------------------------------------------
// xSyncObject 接口类
//------------------------------------------------------------------------
class xSyncObject
{
public:
xSyncObject(void);
public:
// @note: 上锁
virtual BOOL lock(void) /*= 0;*/ { return FALSE; }
// @note: 挂起调用线程,直到该内核对象被解锁
// @param timeout <ulong_t> : 等待时间(毫秒)
virtual BOOL wait(ulong_t timeout = INFINITE) /*= 0;*/ { return FALSE; }
// @note: 解锁
virtual BOOL Unlock(void) /*= 0;*/ { return FALSE; }
// @note: 占用资源并进入访问
virtual BOOL enter(void) /*= 0;*/ { return FALSE; }
// @note: 离开并释放占用资源
virtual BOOL leave(void) /*= 0;*/ { return FALSE; }
public:
virtual ~xSyncObject(void);
};
//------------------------------------------------------------------------
// xEvent 多线程事件同步
// linux 下参考:http://blog.youkuaiyun.com/ffilman/article/details/4871920
//------------------------------------------------------------------------
class xEvent : public xSyncObject
{
#define __signaled(e) ( (e).unlock() )
#define __nonsignaled(e) ( (e).lock() )
#define __wait_signal(e,s) ( (e).wait(s) )
public:
xEvent(
BOOL initstate = FALSE, BOOL manualreset = FALSE
#ifdef WIN32
,LPCTSTR lpName = NULL, LPSECURITY_ATTRIBUTES lpsa = NULL
#else
,u32_t pshared = PTHREAD_PROCESS_PRIVATE
,u32_t type = PTHREAD_MUTEX_TIMED_NP
#endif
);
public:
// @note: 设置事件未受信(non-signaled)状态[人工重置(manual-reset)事件]
/*inline*/ BOOL lock();
// @note: 挂起调用线程,直到该事件对象受信(signaled)
// @param timeout <ulong_t> : 等待时间(毫秒)
/*inline*/ BOOL wait(ulong_t timeout = INFINITE);
// @note: 设置事件受信(signaled)状态
/*inline*/ BOOL unlock();
public:
#ifdef WIN32
HANDLE _event;
#else
#if 0
typedef struct _cond_check_t
{
typedef BOOL (*cond_check_callback_func)(void * args);
cond_check_callback_func _handler;
void * _args;
}cond_check_t;
cond_check_t _cond_check;
#endif
pthread_mutex_t _mutex;
pthread_cond_t _cond;
BOOL _manual_reset,_signaled;
#endif
public:
~xEvent(void);
};
//------------------------------------------------------------------------
// xSemaphore,控制多线程对同一共享资源的并发访问
// linux 下参考:http://blog.youkuaiyun.com/qinxiongxu/article/details/7830537
//------------------------------------------------------------------------
class xSemaphore : public xSyncObject
{
public:
// @note:构造信号内核对象
// @param initvalue <ulong_t> : 初始可用访问资源计数
// @param maxvalue <ulong_t> : 允许最大访问资源计数,指定并发访问共享资源的最大线程数
xSemaphore(ulong_t initvalue = 1
#ifdef WIN32
,ulong_t maxvalue = 1
#endif
,char const * name = NULL);
public:
// @note: 占用资源并进入访问
/*inline*/ BOOL enter();
// @note: 离开并释放占用资源
/*inline*/ BOOL leave();
public:
#ifdef WIN32
HANDLE _sem;
#else
sem_t _sem,*_p_sem;
std::string _S_NAME;
#endif
public:
~xSemaphore(void);
};
//------------------------------------------------------------------------
// xMutex 控制多线程对同一共享资源的互斥访问
//------------------------------------------------------------------------
class xMutex : public xSyncObject
{
public:
xMutex(
#ifdef WIN32
LPCTSTR lpName = NULL, BOOL bInitOwner = FALSE, LPSECURITY_ATTRIBUTES lpsa = NULL
#else
u32_t pshared = PTHREAD_PROCESS_PRIVATE
,u32_t type = PTHREAD_MUTEX_TIMED_NP
#endif
);
public:
// @note: 占用资源并互斥访问
/*inline*/ BOOL enter();
// @note: 离开并释放占用资源
/*inline*/ BOOL leave();
public:
#ifdef WIN32
HANDLE _mutex;
#else
pthread_mutex_t _mutex;
#endif
public:
~xMutex(void);
};
//------------------------------------------------------------------------
// xSection,多线程访问临界资源
//------------------------------------------------------------------------
class xSection : public xSyncObject
{
public:
xSection(
#ifdef WIN32
#else
u32_t pshared = PTHREAD_PROCESS_PRIVATE
,u32_t type = PTHREAD_MUTEX_TIMED_NP
#endif
);
public:
// @note: 占用资源并进入访问
/*inline*/ BOOL enter();
// @note: 离开并释放占用资源
/*inline*/ BOOL leave();
private:
#ifdef WIN32
CRITICAL_SECTION _cs;
#else
pthread_mutex_t _cs;
#endif
public:
~xSection(void);
};
class xThreadPool;
//------------------------------------------------------------------------
// xThread 线程类
//------------------------------------------------------------------------
class xThread
{
friend class xThreadPool;
public:
xThread(void);
xThread(void * argument
#ifndef WIN32
,BOOL detach = FALSE
,u32_t scope = PTHREAD_SCOPE_SYSTEM
,u32_t inherit = PTHREAD_EXPLICIT_SCHED
,u32_t policy = SCHED_OTHER
#endif
,u32_t priority = 0
);
/*virtual*/ BOOL stop() { return this->_done = TRUE; }
public:
inline HANDLE operator *() const { return _handler; }
inline u32_t getid() const { return (u32_t)_tid ; }
inline BOOL active() const { return !this->_done; }
public:
BOOL start(void * argument = NULL
#ifndef WIN32
,BOOL detach = FALSE
,u32_t scope = PTHREAD_SCOPE_SYSTEM // PTHREAD_SCOPE_PROCESS,PTHREAD_SCOPE_SYSTEM
,u32_t inherit = PTHREAD_EXPLICIT_SCHED // 继承性:PTHREAD_EXPLICIT_SCHED,PTHREAD_INHERIT_SCHED
,u32_t policy = SCHED_OTHER // 调度策略:SCHED_FIFO,SCHED_RR,SCHED_OTHER ..
#endif
,u32_t priority = 0
);
BOOL wait(u32_t timeout = INFINITE);
#ifndef WIN32
void detach();
#endif
BOOL setpriority(u32_t priority);
u32_t getpriority();
void suspend();
void resume();
protected:
// @note:run()运行时调用修改优先级
BOOL onpriority();
protected:
void release();
protected:
virtual u32_t __fastcall run(void * argument) = 0;
protected:
typedef struct _thread_param_t
{
xThread * pthis;
void * argument;
}thread_param_t;
thread_param_t _param;
pthread_t _tid;
u32_t _priority; // 待修改的优先级
BOOL _modify; // 修改标记
BOOL _done;
#ifdef WIN32
HANDLE _handler;
// ESMT::xEvent _event;
#endif
private:
static u32_t __stdcall routine(void * lpParam);
public:
virtual ~xThread(void);
};
//------------------------------------------------------------------------
// xThreadPool 线程池
//------------------------------------------------------------------------
class xThreadPool
{
typedef std::map<u32_t,xThread*> map_id_thread_t;
typedef map_id_thread_t::iterator itor_id_thread_t;
public:
xThreadPool(void);
void add(xThread * thread);
void del(u32_t id);
void clear(void);
xThread * get(u32_t id);
size_t size(void);
public:
~xThreadPool(void);
private:
map_id_thread_t _thread_pool;
};
} // namespace ESMT
#endif // _XTHREAD_H_INCLUDE_
/*
* @note :同步事件/信号量/互斥/临界区/线程/线程池实现(win32/linux),不支持unicode
* @author :Andy.Ro
* @email :Qwuloo@qq.com
*/
#include "xThread.h"
namespace ESMT {
//------------------------------------------------------------------------
// xSyncObject
//------------------------------------------------------------------------
xSyncObject::xSyncObject(void)
{
}
xSyncObject::~xSyncObject(void)
{
} // class xSyncObject
#ifndef WIN32
static inline int s_pthread_cond_init(pthread_cond_t * cond, int pshared = PTHREAD_PROCESS_PRIVATE)
{
pthread_condattr_t attr = {0};
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, pshared);
int err = pthread_cond_init(cond, &attr);
pthread_condattr_destroy(&attr);
return err;
}
static inline int s_pthread_mutex_init(pthread_mutex_t * mutex, u32_t pshared = PTHREAD_PROCESS_PRIVATE, u32_t type = PTHREAD_MUTEX_TIMED_NP)
{
pthread_mutexattr_t attr = {0};
pthread_mutexattr_init(&attr);
// PTHREAD_PROCESS_PRIVATE:同一进程内不同线程间同步
// PTHREAD_PROCESS_SHARED :进程间同步
pthread_mutexattr_setpshared(&attr, pshared);
// PTHREAD_MUTEX_TIMED_NP (普通锁):互斥访问
// PTHREAD_MUTEX_RECURSIVE_NP (嵌套锁)
// PTHREAD_MUTEX_ERRORCHECK_NP(检错锁)
// PTHREAD_MUTEX_ADAPTIVE_NP (适应锁)
pthread_mutexattr_settype(&attr, type);
int err = pthread_mutex_init(mutex, &attr);
pthread_mutexattr_destroy(&attr);
return err;
}
static inline int s_pthread_mutex_lock(pthread_mutex_t * mutex)
{
return pthread_mutex_lock(mutex);
}
static inline int s_pthread_mutex_unlock(pthread_mutex_t * mutex)
{
return pthread_mutex_unlock(mutex);
}
static inline int s_pthread_mutex_trylock(pthread_mutex_t * mutex)
{
return pthread_mutex_trylock(mutex);
}
static inline int s_pthread_mutex_destroy(pthread_mutex_t * mutex)
{
return pthread_mutex_destroy(mutex);
}
#endif
//------------------------------------------------------------------------
// xEvent
//------------------------------------------------------------------------
xEvent::xEvent(
BOOL initstate /* = FALSE */, BOOL manualreset /* = FALSE */
#ifdef WIN32
,LPCTSTR lpName /* = NULL */, LPSECURITY_ATTRIBUTES lpsa /* = NULL */
#else
,u32_t pshared /* = PTHREAD_PROCESS_PRIVATE */
,u32_t type /* = PTHREAD_MUTEX_TIMED_NP */
#endif
)
{
// 事件内核对象
#ifdef WIN32
this->_event = CreateEvent(lpsa, manualreset, initstate, lpName);
#else
bzero(&this->_cond_check, sizeof(cond_check_t));
// pthread_mutex_init(&this->_mutex, NULL);
// pthread_cond_init(&this->_cond, NULL);
s_pthread_mutex_init(&this->_mutex, pshared, type);
s_pthread_cond_init(&this->_cond, pshared);
this->_signaled = initstate;
this->_manual_reset = manualreset;
#endif
}
BOOL xEvent::lock(void)
{
// 未受信(non-signaled)
// 人工重置(manual-reset)事件:所有等待在该事件上的线程均变为不可调度状态
// 自动重置(auto-reset )事件:调用无效,因为设置事件为受信状态后,系统会立即自动重置为未受信状态,且仅
// 允许一个等待在该事件上的线程变为可调度状态,挂起其他等待在该事件上的线程
#ifdef WIN32
return ResetEvent(this->_event);
#else
pthread_mutex_lock(&this->_mutex);
if ( this->_manual_reset )
{
this->_signaled = FALSE;
}
return 0 == pthread_mutex_unlock(&this->_mutex);
#endif
}
BOOL xEvent::wait(ulong_t timeout /* = INFINITE */)
{
#ifdef WIN32
return WAIT_OBJECT_0 == WaitForSingleObject(this->_event, timeout);
#else
pthread_mutex_lock(&this->_mutex);
#if 0
while( this->_cond_check._handler && !(*this->_cond_check._handler)(this->cond_check._args) )
#else
while( !this->_signaled )
#endif
{
if ( INFINITE == timeout )
{
if ( pthread_cond_wait(&this->_cond, &this->_mutex) )
{
pthread_mutex_unlock(&this->_mutex);
return -1;
}
}
else {
// timeout:毫秒 tv_usec:微秒 tv_nsec:纳秒
struct timeval tv = {0};
struct timespec abstm = {0};
gettimeofday(&tv, NULL);
abstm.tv_sec = tv.tv_sec + timeout / 1000;
abstm.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000000;
int err;
if ( err = pthread_cond_timedwait(&this->_cond, &this->_mutex, &abstm) )
{
if (ETIMEDOUT == err ) {
break;
}
pthread_mutex_unlock(&this->_mutex);
return -1;
}
}
}
// 自动重置(auto-reset )事件受信后,立即重置为未受信状态
if ( !this->_manual_reset )
{
this->_signaled = FALSE;
}
return 0 == pthread_mutex_unlock(&this->_mutex);
#endif
}
BOOL xEvent::unlock(void)
{
// 受信(signaled)
// 人工重置(manual-reset)事件:所有等待在该事件上的线程均变为可调度状态
// 自动重置(auto-reset )事件:仅允许一个等待在该事件上的线程变为可调度状态,然后系统立即自动重置为未受信状态,
// 挂起其他等待在该事件上的线程
#ifdef WIN32
return SetEvent(this->_event);
#else
pthread_mutex_lock(&this->_mutex);
this->_signaled = TRUE;
int err = this->_manual_reset?pthread_cond_broadcast(&this->_cond):pthread_cond_signal(&this->_cond);
pthread_mutex_unlock(&this->_mutex);
return 0 == err;
#endif
}
#pragma endregion
xEvent::~xEvent(void)
{
#ifdef WIN32
SAFE_DEL_HDL(this->_event);
#else
this->_signaled = TRUE;
pthread_cond_destroy(&this->_cond);
pthread_mutex_destroy(&this->_mutex);
#endif
} // class xEvent
//------------------------------------------------------------------------
// xSemaphore
//------------------------------------------------------------------------
xSemaphore::xSemaphore(ulong_t initvalue /* = 1 */
#ifdef WIN32
,ulong_t maxvalue /* = 1 */
#endif
,char const * name /* = NULL */)
{
// 信号量内核对象
#ifdef WIN32
if ( !(this->_sem = CreateSemaphore(NULL, initvalue, maxvalue, (LPCTSTR)name)) )
{
if ( ERROR_ALREADY_EXISTS == GetLastError() )
{
if( !(this->_sem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, (LPCTSTR)name)) )
{
// fprintf(stderr, "OpenSemaphore error: %s\n", strerror(GetLastError()));
perror("OpenSemaphore error");
}
return;
}
// fprintf(stderr, "CreateSemaphore error: %s\n", strerror(GetLastError()));
perror("CreateSemaphore error");
}
#else
if( !name )
{
// 初始化一个进程内线程间共享的匿名信号量
// 进程间共享则第二个参数pshared必须大于0,且须定位共享内存区( shm_open,mmap,shmget,shmat),要注意的是匿名信号量的值是保存在内存中,所以只能用于亲缘进程间共享
if( sem_init(&this->_sem, 0, min(initvalue, SEM_VALUE_MAX)) < 0 )
{
// fprintf(stderr, "sem_init error: %s\n", strerror(errno));
perror("sem_init error");
bzero(&this->_sem, sizeof(sem_t));
}
}
else {
// 打开一个有名信号量,没有则创建,既可用于进程内线程间,亲缘进程间,也可用于不相干进程间共享
// 注意:第一次创建,第二次打开,initvalue 值设为 0,用于共享同步访问
if( SEM_FAILED == (this->_p_sem = sem_open(name, O_CREAT, 0644, min(initvalue, SEM_VALUE_MAX))) ) {
// fprintf(stderr, "sem_open error: %s\n", strerror(errno));
perror("sem_open error");
sem_unlink(name);
this->_p_sem = NULL;
return;
}
this->_S_NAME = name;
}
#endif
}
BOOL xSemaphore::enter(void)
{
#ifdef WIN32
return WAIT_OBJECT_0 == WaitForSingleObject(this->_sem, INFINITE);
#else
return 0 == sem_wait(this->_p_sem?this->_p_sem:&this->_sem); // P操作,即申请资源
#endif
}
BOOL xSemaphore::leave(void)
{
#ifdef WIN32
return ReleaseSemaphore(this->_sem, 1, NULL);
#else
return 0 == sem_post(this->_p_sem?this->_p_sem:&this->_sem); // V操作,即释放资源
#endif
}
xSemaphore::~xSemaphore(void)
{
#ifdef WIN32
SAFE_DEL_HDL(this->_sem);
#else
this->_p_sem?sem_close(this->_p_sem):sem_destroy(this->_sem);
this->_p_sem?sem_unlink(this->_S_NAME.c_str());
this->_p_sem = NULL;
bzero(&this->_sem, sizeof(sem_t));
#endif
} // class xSemaphore
//------------------------------------------------------------------------
// xMutex
//------------------------------------------------------------------------
xMutex::xMutex(
#ifdef WIN32
LPCTSTR lpName /* = NULL */, BOOL bInitOwner /* = FALSE */, LPSECURITY_ATTRIBUTES lpsa /* = NULL */
#else
,u32_t pshared /* = PTHREAD_PROCESS_PRIVATE */
,u32_t type /* = PTHREAD_MUTEX_TIMED_NP */
#endif
)
{
// 互斥内核对象只有一个,仅拥有互斥对象的线程才具有访问资源权限,互斥访问共享资源时只能一个线程占用并访问,
// 访问完后占用资源的线程要释放当前占用资源(交出拥有的互斥内核对象),以让其他线程再竞争占用共享资源进行互斥访问
#ifdef WIN32
this->_mutex = CreateMutex(lpsa, bInitOwner, lpName);
#else
s_pthread_mutex_init(&this->_mutex, pshared, type);
#endif
}
/*inline*/ BOOL xMutex::enter(void)
{
#ifdef WIN32
return WAIT_OBJECT_0 == WaitForSingleObject(this->_mutex, INFINITE);
#else
return 0 == s_pthread_mutex_lock(&this->_mutex);
#endif
}
/*inline*/ BOOL xMutex::leave(void)
{
// 释放互斥对象
#ifdef WIN32
return ReleaseMutex(this->_mutex);
#else
return 0 == s_pthread_mutex_unlock(&this->_mutex);
#endif
}
xMutex::~xMutex(void)
{
#ifdef WIN32
SAFE_DEL_HDL(this->_mutex);
#else
s_pthread_mutex_destroy(&this->_mutex);
#endif
} // class xMutex
//------------------------------------------------------------------------
// xSection
//------------------------------------------------------------------------
xSection::xSection(
#ifdef WIN32
#else
u32_t pshared /* = PTHREAD_PROCESS_PRIVATE */
,u32_t type /* = PTHREAD_MUTEX_TIMED_NP */
#endif
)
{
// 使用临界区对象能实现多线程对共享数据的同步访问,但是非内核对象,所以不能用于进程间线程同步
#ifdef WIN32
InitializeCriticalSection(&this->_cs);
#else
s_pthread_mutex_init(&this->_cs, pshared, type);
#endif
}
/*inline*/ BOOL xSection::enter(void)
{
#ifdef WIN32
EnterCriticalSection(&this->_cs);
#else
return 0 == s_pthread_mutex_lock(&this->_cs);
#endif
return TRUE;
}
/*inline*/ BOOL xSection::leave(void)
{
#ifdef WIN32
LeaveCriticalSection(&this->_cs);
#else
return 0 == s_pthread_mutex_unlock(&this->_cs);
#endif
return TRUE;
}
xSection::~xSection(void)
{
#ifdef WIN32
DeleteCriticalSection(&this->_cs);
#else
s_pthread_mutex_destroy(&this->_cs);
#endif
} // class xSection
//------------------------------------------------------------------------
// xThread
//------------------------------------------------------------------------
xThread::xThread()
:_tid(0)
,_priority(0)
,_done(FALSE)
,_modify(FALSE)
#ifdef WIN32
,_handler(NULL)
#endif
{
bzero(&this->_param, sizeof(thread_param_t));
}
xThread::xThread(void * argument
#ifndef WIN32
,BOOL detach /* = FALSE */
,u32_t scope /* = PTHREAD_SCOPE_SYSTEM */
,u32_t inherit /* = PTHREAD_EXPLICIT_SCHED */
,u32_t policy /* = SCHED_OTHER */
#endif
,u32_t priority /* = 0 */
)
:_tid(0)
,_priority(0)
,_done(FALSE)
,_modify(FALSE)
#ifdef WIN32
,_handler(NULL)
#endif
{
bzero(&this->_param, sizeof(thread_param_t));
this->start(argument
#ifndef WIN32
,detach
,scope
,inherit
,policy
#endif
,priority
);
}
BOOL xThread::start(void * argument /* = NULL */
#ifndef WIN32
,BOOL detach /* = FALSE */
,u32_t scope /* = PTHREAD_SCOPE_SYSTEM */
,u32_t inherit /* = PTHREAD_EXPLICIT_SCHED */
,u32_t policy /* = SCHED_OTHER */
#endif
,u32_t priority /* = 0 */
)
{
if( !this->_tid )
{
bzero(&this->_param, sizeof(thread_param_t));
this->_param.pthis = this;
this->_param.argument = argument;
#ifdef WIN32
// ...
_handler = (HANDLE)_beginthreadex(NULL, // security
0, // stack size
xThread::routine, // start address
(void *)&this->_param, // argument list
0, // init flag:0 | CREATE_SUSPENDED
(unsigned *)&this->_tid); // thread id
if( !this->_tid ) {
// fprintf(stderr, "_beginthreadex error: %s\n", strerror(GetLastError()));
perror("_beginthreadex error");
return FALSE;
}
this->setpriority(priority);
// SAFE_DEL_HDL(_handler);
#else
pthread_attr_t atrr = {0};
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, scope);
pthread_attr_setinheritsched(&attr, inherit);
PTHREAD_EXPLICIT_SCHED == inherit?pthread_attr_setschedpolicy(&attr, policy):0;
detach?pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)
:pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
if ( SCHED_RR == policy || SCHED_FIFO == policy ) {
sched_param param = {0};
priority = MIN(priority,sched_get_priority_max(policy));
priority = MAX(priority,sched_get_priority_min(policy));
pthread_attr_getschedparam(&attr, ¶m);
param.sched_priority = priority;
pthread_attr_setschedparam(&attr, ¶m);
}
// ...
int err;
if ( err = pthread_create(&this->_tid, attr, xThread::routine, (void *)argument) ) {
// fprintf(stderr, "pthread_create error: %s\n", strerror(err));
perror("pthread_create error");
pthread_attr_destroy(&attr);
return FALSE;
}
pthread_attr_destroy(&attr);
#endif
this->_done = FALSE;
}
return 0 != this->_tid;
}
u32_t __stdcall xThread::routine(void * lpParam)
{
thread_param_t * pParam = (thread_param_t *)lpParam;
u32_t result = pParam->pthis->run(pParam->argument);
// __signaled(pParam->pthis->_event);
pParam->pthis->release();
#ifdef WIN32
_endthreadex(0);
#else
pthread_exit(0);
#endif
return result;
}
BOOL xThread::wait(u32_t timeout /* = INFINITE */)
{
#ifdef WIN32
assert( this->_handler );
#if 1
return WAIT_FAILED != WaitForSingleObject(this->_handler, timeout);
#else
// 等待线程运行结束退出,线程创建后句柄已被关闭,换用事件方式
return __wait_signal(this->_event, timeout);
#endif
#else
assert( this->_tid );
return 0 == pthread_join(this->_tid, NULL);
#endif
}
#ifndef WIN32
void xThread::detach()
{
pthread_detach(this->_tid);
}
#endif
BOOL xThread::setpriority(u32_t priority)
{
#ifdef WIN32
#else
u32_t policy;
sched_param param = {0};
pthread_getschedparam(this->_tid, &policy, ¶m);
if ( SCHED_RR != policy || SCHED_FIFO != policy )
{
return FALSE;
}
priority = MIN(priority,sched_get_priority_max(policy));
priority = MAX(priority,sched_get_priority_min(policy));
#endif
this->_priority = priority;
this->_modify = TRUE;
return TRUE;
}
// @note:线程运行时调用修改优先级
BOOL xThread::onpriority()
{
if ( this->_modify )
{
this->_modify = FALSE;
#ifdef WIN32
assert( this->_tid == GetThreadId(_handler) );
return SetThreadPriority(_handler, this->_priority);
#else
assert( this->_tid == pthread_self() );
u32_t policy;
sched_param param = {0};
pthread_getschedparam(this->_tid, &policy, ¶m);
assert( SCHED_RR == policy || SCHED_FIFO == policy );
param.sched_priority = this->_priority;
pthread_setschedparam(this->_tid, policy, ¶m);
#endif
}
return TRUE;
}
u32_t xThread::getpriority()
{
#ifdef WIN32
assert( this->_tid && this->_handler );
return GetThreadPriority(this->_handler);
#else
assert( this->_tid );
u32_t policy;
sched_param param;
pthread_getschedparam(this->_tid, &policy, ¶m);
return param.sched_priority;
#endif
}
void xThread::suspend()
{
#ifdef WIN32
SuspendThread(_handler);
#endif
}
void xThread::resume()
{
#ifdef WIN32
ResumeThread(_handler);
#endif
}
void xThread::release()
{
SAFE_DEL_HDL(_handler);
this->_tid = 0;
bzero(&this->_param, sizeof(thread_param_t));
}
xThread::~xThread()
{
release();
} // class xThread
//------------------------------------------------------------------------
// xThreadPool
//------------------------------------------------------------------------
xThreadPool::xThreadPool(void)
{
this->_thread_pool.clear();
}
void xThreadPool::add(xThread * thread)
{
this->_thread_pool[thread->getid()] = thread;
}
void xThreadPool::del(u32_t id)
{
itor_id_thread_t itor = this->_thread_pool.find(id);
if ( itor != this->_thread_pool.end() )
{
// 关闭指定线程
itor->second->stop();
BOOL delflag = FALSE;
while ( !delflag )
{
// 挂起调用线程等待指定线程结束
if ( __wait_signal(*itor->second,1000) )
{
delflag = TRUE;
SAFE_DEL(itor->second);
this->_thread_pool.erase(itor);
}
}
}
}
void xThreadPool::clear(void)
{
// 线程池中还有残留线程
while ( this->_thread_pool.size() )
{
itor_id_thread_t itor = this->_thread_pool.begin();
for ( ; itor != this->_thread_pool.end(); )
{
// 关闭指定线程
itor->second->stop();
// 挂起调用线程等待指定线程结束
if ( __wait_signal(*itor->second,1000) )
{
SAFE_DEL(itor->second);
this-> _thread_pool.erase(itor);
itor = _thread_pool.begin();
continue;
}
++itor;
}
}
}
xThread * xThreadPool::get(u32_t id)
{
return this->_thread_pool[id];
}
size_t xThreadPool::size(void)
{
return this->_thread_pool.size();
}
xThreadPool::~xThreadPool(void)
{
this->clear();
} // class xThreadPool
} // namespace ESMT