//Thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
#ifdef _WIN32
# include <windows.h>
# include <process.h>
#else
# include <pthread.h>
#endif
//可运行基类
class IRunable {
public:
//构造函数
IRunable() {}
//析构函数
virtual ~IRunable() {}
//线程运行入口
virtual void run() = 0;
};
typedef unsigned int ThreadId;
class Thread : public IRunable {
public:
Thread();
/**
* @param target 线程运行目标
* @param release 目标对象是否由线程对象释放
*/
Thread(IRunable& target, bool release = true);
virtual ~Thread();
void start();
virtual void run();
void join();
void detach();
ThreadId getThreadId() const;
bool operator == (const Thread& rhs) const;
bool operator != (const Thread& rhs) const;
bool operator < (const Thread& rhs) const;
public:
static void start(IRunable& target);
static void sleep(int millis);
static ThreadId getCurrentThreadId();
static void yield();
private:
IRunable* _target;
bool _release;
#ifdef _WIN32
ThreadId _threadId;
HANDLE _pThread;
#else
pthread_t _pThread;
#endif
};
#endif //_THREAD_H_
//Thread.cpp
#include "Thread.h"
#ifdef _WIN32
# include <process.h>
#endif
#include <iostream>
#include <exception>
using std::exception;
//线程运行入口
#ifdef _WIN32
unsigned int _stdcall
#else
void*
#endif
runEntry(void* target) {
try{
reinterpret_cast<IRunable*>(target)->run();
} catch(const exception& ex) {
std::cerr << ex.what() << std::endl;
} catch(...){
std::cerr << "run error" << std::endl;
}
return 0;
}
Thread::Thread() : _target(NULL), _release(false), _pThread(0) {
#ifdef _WIN32
_threadId = 0;
_pThread = INVALID_HANDLE_VALUE;
#else
_pThread = 0;
#endif
}
Thread::Thread(IRunable& target, bool release) : _target(&target), _release(release), _pThread(0) {
#ifdef _WIN32
_threadId = 0;
_pThread = INVALID_HANDLE_VALUE;
#else
_pThread = 0;
#endif
}
Thread::~Thread() {
if(_release)
delete _target;
}
//线程入口
void Thread::run() {}
void Thread::start() {
IRunable* target = _target ? _target : this;
#ifdef _WIN32
_pThread = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, runEntry, target, 0, &_threadId));
if(0 == _pThread) {
throw exception();//GetLastError()
}
#else
pthread_attr_t attr;
int rc = pthread_attr_init(&attr);
if(rc) {
throw exception();//errno
}
rc = pthread_create(&_pThread, &attr, runEntry, target);
if(rc) {
throw exception();//errno
}
#endif
}
void Thread::join() {
#ifdef _WIN32
if(_pThread && WaitForSingleObject(_pThread, INFINITE) != WAIT_OBJECT_0){
throw exception();//GetLastError()
}
detach();
#else
if(_pThread && pthread_join(_pThread, NULL) != 0) {
throw exception();//errno
}
#endif
}
void Thread::detach() {
#ifdef _WIN32
if(_pThread && CloseHandle(_pThread) == 0){
throw exception();//GetLastError()
}
#else
if(_pThread && pthread_detach(_pThread) != 0){
throw exception();//errno
}
#endif
}
ThreadId Thread::getThreadId() const {
#ifdef _WIN32
return _threadId;
#else
return _pThread;
#endif
}
bool Thread::operator == (const Thread& rhs) const {
return this == &rhs;
}
bool Thread::operator != (const Thread& rhs) const {
return this != &rhs;
}
bool Thread::operator < (const Thread& rhs) const {
return this < &rhs;
}
// static functions
void Thread::start(IRunable& target) {
Thread t(target, false);
t.start();
t.detach();
}
void Thread::sleep(int ms) {
#ifdef _WIN32
Sleep(ms);
#else
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&ts, 0);
#endif
}
ThreadId Thread::getCurrentThreadId() {
#ifdef _WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
void Thread::yield() {
#ifdef _WIN32
Sleep(0);
#else
sched_yield();
#endif
}
//main.cpp
#include "Thread.h"
#include <iostream>
class TestThread : public Thread {
public:
virtual void run() {
std::cout << "this is a thread test" << std::endl;
std::cout << Thread::getCurrentThreadId() << std::endl;
}
};
int main(int argc, char const *argv[])
{
TestThread test;
test.start();
//test.detach();
test.join();
return 0;
}