c++简单线程封装(一)

2014-11-24 09:23:20 · 作者: · 浏览: 3

模仿boost,用 tls 实现 interrupt 功能

thread.h

[cpp]
#pragma once

#include <windows.h>
#include
using namespace std;

#include "singleton.h"
#include "locker.h"

namespace thread {


struct thread;
DWORD WINAPI ThreadFunc(void* thrd);
thread* get_current_thread_data();
void interruption_point();

// #define TLS_OUT_OF_INDEXES 0xFFFFFFFF
DWORD current_thread_tls_key = TLS_OUT_OF_INDEXES;

struct tls_alloc_once : public singleton {
locker lock;
tls_alloc_once() {
lock.lock();
current_thread_tls_key = TlsAlloc();
lock.unlock();
}
};

struct interrupt_exception {};

struct thread_data {
bool interrupted;
typedef function f_type;
f_type _f;

thread_data() : interrupted(false) {}

template
thread_data(F f) : _f(f), interrupted(false) {}

void run() {
if(_f) _f();
}
};


struct thread {
thread_data _data;
HANDLE _h;
DWORD _id;

thread() {}
thread(thread_data data) : _data(data) {}

void start() {
_h = CreateThread(NULL, 0, ThreadFunc, (void*)this, 0, &_id);
}
void join() {
::WaitForSingleObject(_h, INFINITE);
}
void operator=(thread_data data) {
_data = data;
}
void interrupt() {
_data.interrupted = true;
}
};
DWORD WINAPI ThreadFunc(void* thrd) {
tls_alloc_once::instance();
if(current_thread_tls_key == TLS_OUT_OF_INDEXES)
throw std::exception("tls alloc error");

if(!::TlsSetValue(current_thread_tls_key, thrd))
throw std::exception("tls setvalue error");

try {
static_cast(thrd)->_data.run();
} catch(interrupt_exception&) {}
return 0;
}
void interruption_point() {
thread* thrd = get_current_thread_data();
if(!thrd) throw std::exception("no thread, wth");
if(thrd->_data.interrupted) {
thrd->_data.interrupted = false;
throw interrupt_exception();
}
}
thread* get_current_thread_data() {
if(current_thread_tls_key == TLS_OUT_OF_INDEXES) {
return NULL;
}
return (thread*)TlsGetValue(current_thread_tls_key);
}

}; // end of namespace thread

locker.h
[cpp]
#pragma once

#include "windows.h"

class locker {
public:
locker() {
::InitializeCriticalSection(&cs);
}
~locker() {
::DeleteCriticalSection(&cs);
}
void lock() const {
::EnterCriticalSection(&cs);
}
void unlock() const {
::LeaveCriticalSection(&cs);
}
private:
mutable ::CRITICAL_SECTION cs;
};

singleton.h
[cpp]
#pragma once
template
class singleton {
public:
static inline T& instance() {
static T _instance;
return _instance;
}
};

测试:
[cpp]
#include
#include
using namespace std;

#include "thread.h"
using namespace thread;

void S1() {
while(1) {
interruption_point();
cout << "S1()" << endl;
Sleep(1000);
}
}
void S2() {
while(1) {
interruption_point();
cout << "S2()" << endl;
Sleep(500);
}
}

int main() {
thread t1(S1);
thread t2;
t2 = S2;
thread t3([&]() {
Sleep(2000);
t2.interrupt();
t2.join();
Sleep(2000);
t2.start();
cout << "t3 over" << endl;
});

t1.start();// always running
t2.start();// interrupted after 2 seconds and restart after 4 secon