程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 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; 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved