当前位置:编程学习 > C/C++ >>

c++简单线程封装

模仿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;&n

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,