2019-08-31 18:54:22 +00:00
|
|
|
|
#ifndef __EX_THREAD_H__
|
2016-12-14 15:34:44 +00:00
|
|
|
|
#define __EX_THREAD_H__
|
|
|
|
|
|
2017-09-16 17:04:42 +00:00
|
|
|
|
#include "ex_str.h"
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
|
|
#ifdef EX_OS_WIN32
|
2020-10-14 18:50:33 +00:00
|
|
|
|
# include <process.h>
|
2016-12-14 15:34:44 +00:00
|
|
|
|
typedef HANDLE EX_THREAD_HANDLE;
|
2020-11-02 16:57:26 +00:00
|
|
|
|
# define EX_THREAD_NULL NULL
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
|
|
|
|
|
# include <pthread.h>
|
|
|
|
|
# include <sys/time.h>
|
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
typedef pthread_t EX_THREAD_HANDLE;
|
2020-11-02 16:57:26 +00:00
|
|
|
|
|
|
|
|
|
# if defined(EX_OS_LINUX)
|
|
|
|
|
# define EX_THREAD_NULL 0
|
|
|
|
|
# elif defined(EX_OS_MACOS)
|
|
|
|
|
# define EX_THREAD_NULL nullptr
|
|
|
|
|
# endif
|
|
|
|
|
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
class ExThreadBase
|
2016-12-06 17:05:56 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
explicit ExThreadBase(const char* thread_name);
|
|
|
|
|
virtual ~ExThreadBase();
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
bool is_running() const
|
|
|
|
|
{
|
|
|
|
|
return m_is_running;
|
|
|
|
|
}
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
// 创建并启动线程(执行被重载了的run()函数)
|
|
|
|
|
bool start();
|
|
|
|
|
// 结束线程(等待wait_timeout_ms毫秒,如果wait_timeout_ms为0,则无限等待)
|
|
|
|
|
bool stop();
|
|
|
|
|
// 直接结束线程(强杀,不建议使用)
|
|
|
|
|
bool terminate();
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
protected:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
// main loop of this thread.
|
|
|
|
|
virtual void _thread_loop() = 0;
|
|
|
|
|
|
|
|
|
|
// called by another thread when thread ready to stop.
|
|
|
|
|
virtual void _on_stop()
|
|
|
|
|
{
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-03 06:11:02 +00:00
|
|
|
|
// called inside thread when thread fully stopped.
|
2020-10-14 18:50:33 +00:00
|
|
|
|
virtual void _on_stopped()
|
|
|
|
|
{
|
|
|
|
|
};
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
#ifdef EX_OS_WIN32
|
2020-10-14 18:50:33 +00:00
|
|
|
|
static unsigned int WINAPI _thread_func(LPVOID lpParam);
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
static void* _thread_func(void* pParam);
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
protected:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
ex_astr m_thread_name;
|
|
|
|
|
EX_THREAD_HANDLE m_handle;
|
|
|
|
|
bool m_is_running;
|
|
|
|
|
bool m_need_stop;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2019-08-31 18:54:22 +00:00
|
|
|
|
// 线程锁(进程内使用)
|
2016-12-14 15:34:44 +00:00
|
|
|
|
class ExThreadLock
|
2016-12-06 17:05:56 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
ExThreadLock();
|
|
|
|
|
virtual ~ExThreadLock();
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
void lock();
|
|
|
|
|
void unlock();
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#ifdef EX_OS_WIN32
|
2020-10-14 18:50:33 +00:00
|
|
|
|
CRITICAL_SECTION m_locker;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
pthread_mutex_t m_locker;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-31 18:54:22 +00:00
|
|
|
|
// 线程锁辅助类
|
2016-12-14 15:34:44 +00:00
|
|
|
|
class ExThreadSmartLock
|
2016-12-06 17:05:56 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
explicit ExThreadSmartLock(ExThreadLock& lock) :
|
|
|
|
|
m_lock(lock)
|
|
|
|
|
{
|
|
|
|
|
m_lock.lock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ExThreadSmartLock()
|
|
|
|
|
{
|
|
|
|
|
m_lock.unlock();
|
|
|
|
|
}
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
private:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
ExThreadLock& m_lock;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
typedef std::list<ExThreadBase*> ex_threads;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
class ExThreadManager
|
2016-12-06 17:05:56 +00:00
|
|
|
|
{
|
2020-10-14 18:50:33 +00:00
|
|
|
|
friend class ExThreadBase;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
public:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
ExThreadManager();
|
|
|
|
|
virtual ~ExThreadManager();
|
|
|
|
|
|
|
|
|
|
void stop_all();
|
|
|
|
|
|
|
|
|
|
//private:
|
|
|
|
|
void add(ExThreadBase* tb);
|
|
|
|
|
void remove(ExThreadBase* tb);
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
private:
|
|
|
|
|
ExThreadLock m_lock;
|
|
|
|
|
ex_threads m_threads;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Event
|
|
|
|
|
class ExEventHelper;
|
|
|
|
|
|
|
|
|
|
class ExEvent
|
|
|
|
|
{
|
|
|
|
|
friend class ExEventHelper;
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
public:
|
|
|
|
|
ExEvent()
|
|
|
|
|
{
|
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
|
|
|
|
pthread_mutex_init(&m_mutex, nullptr);
|
|
|
|
|
pthread_cond_init(&m_cond, nullptr);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ExEvent()
|
|
|
|
|
{
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
pthread_mutex_destroy(&m_mutex);
|
|
|
|
|
pthread_cond_destroy(&m_cond);
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#endif
|
2020-10-14 18:50:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void wait()
|
|
|
|
|
{
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
pthread_cond_wait(&m_cond, &m_mutex);
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#endif
|
2020-10-14 18:50:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void wait_timeout_ms(int timeout_ms)
|
|
|
|
|
{
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
// timeval.tv_usec ==== ms
|
|
|
|
|
// timespec.tv_nsec === nano-second
|
2021-07-12 08:22:55 +00:00
|
|
|
|
struct timeval now = {0};
|
|
|
|
|
struct timespec out_time = {0};
|
2020-10-14 18:50:33 +00:00
|
|
|
|
gettimeofday(&now, nullptr);
|
|
|
|
|
|
|
|
|
|
uint64_t abs_time_ms = now.tv_sec * 1000ll + now.tv_usec + timeout_ms;
|
2021-07-12 08:22:55 +00:00
|
|
|
|
out_time.tv_sec = abs_time_ms / 1000ll;
|
2020-10-14 18:50:33 +00:00
|
|
|
|
out_time.tv_nsec = (long)((abs_time_ms % 1000ll) * 1000ll);
|
|
|
|
|
|
|
|
|
|
pthread_cond_timedwait(&m_cond, &m_mutex, &out_time);
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#endif
|
2020-10-14 18:50:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void signal()
|
|
|
|
|
{
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
2020-10-14 18:50:33 +00:00
|
|
|
|
pthread_cond_signal(&m_cond);
|
2021-03-07 17:13:00 +00:00
|
|
|
|
#endif
|
2020-10-14 18:50:33 +00:00
|
|
|
|
}
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
private:
|
2020-10-14 18:50:33 +00:00
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
|
|
|
|
pthread_mutex_t m_mutex;
|
2021-07-12 08:22:55 +00:00
|
|
|
|
pthread_cond_t m_cond;
|
2020-10-14 18:50:33 +00:00
|
|
|
|
#endif
|
2016-12-06 17:05:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-10-14 18:50:33 +00:00
|
|
|
|
class ExEventHelper
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ExEventHelper(ExEvent& event) :
|
2021-07-12 08:22:55 +00:00
|
|
|
|
m_event(event)
|
2020-10-14 18:50:33 +00:00
|
|
|
|
{
|
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
|
|
|
|
pthread_mutex_lock(&m_event.m_mutex);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ExEventHelper()
|
|
|
|
|
{
|
|
|
|
|
#ifdef EX_OS_WIN32
|
|
|
|
|
#else
|
|
|
|
|
pthread_mutex_unlock(&m_event.m_mutex);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
ExEvent& m_event;
|
|
|
|
|
};
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2019-08-31 18:54:22 +00:00
|
|
|
|
// 原子操作
|
2016-12-14 15:34:44 +00:00
|
|
|
|
int ex_atomic_add(volatile int* pt, int t);
|
2021-07-12 08:22:55 +00:00
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
int ex_atomic_inc(volatile int* pt);
|
2021-07-12 08:22:55 +00:00
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
int ex_atomic_dec(volatile int* pt);
|
2016-12-06 17:05:56 +00:00
|
|
|
|
|
2019-08-31 18:54:22 +00:00
|
|
|
|
// 线程相关操作
|
2020-11-01 18:50:49 +00:00
|
|
|
|
uint64_t ex_get_thread_id();
|
2017-01-08 15:53:37 +00:00
|
|
|
|
|
2016-12-14 15:34:44 +00:00
|
|
|
|
#endif // __EX_THREAD_H__
|