模仿boost,用 tls 實現 interrupt 功能
thread.h
[cpp]
#pragma once
#include <windows.h>
#include <functional>
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<tls_alloc_once> {
locker lock;
tls_alloc_once() {
lock.lock();
current_thread_tls_key = TlsAlloc();
lock.unlock();
}
};
struct interrupt_exception {};
struct thread_data {
bool interrupted;
typedef function<void()> f_type;
f_type _f;
thread_data() : interrupted(false) {}
template<typename F>
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<thread*>(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 T>
class singleton {
public:
static inline T& instance() {
static T _instance;
return _instance;
}
};
測試:
[cpp]
#include <windows.h>
#include <iostream>
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 seconds
t3.start();
t1.join();
t2.join();
return 0;
}