zoukankan      html  css  js  c++  java
  • c++ 精简版 thread

    mutex.h // MinGW 4.7 暂不支持 <mutex>,临时用这个代替

    // MinGW doesn't provide <mutex> ...
    #pragma once
    namespace std {
    
    struct once_flag {
    	bool f;
    	once_flag(bool f = false) : f(f) {}
    };
    template<typename fn_t, typename... args_t>
    void call_once(once_flag& flag, fn_t fn, args_t... args) {
    	if(!flag.f) {
    		flag.f = true;
    		fn(args...);
    	}
    }
    
    }
    

    thread.h

    #pragma once
    
    #include <windows.h>
    #include <functional>
    #include <stdexcept>
    using namespace std;
    
    #include "mutex.h"
    
    typedef unsigned long ulong;
    
    namespace threading {
    
    
    struct thread;
    ulong WINAPI ThreadFunc(void* thrd);
    thread* get_current_thread_data();
    void interruption_point();
    
    // #define TLS_OUT_OF_INDEXES 0xFFFFFFFF
    ulong current_thread_tls_key = TLS_OUT_OF_INDEXES;
    
    
    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;
    	ulong _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;
    	}
    };
    
    std::once_flag thread_tls_once_flag;
    
    ulong WINAPI ThreadFunc(void* thrd) {
    	std::call_once(thread_tls_once_flag, [&]() {
    		current_thread_tls_key = TlsAlloc();
    	});
    	if(current_thread_tls_key == TLS_OUT_OF_INDEXES)
    		throw std::runtime_error("tls alloc error");
    
    	if(!::TlsSetValue(current_thread_tls_key, thrd)) 
    		throw std::runtime_error("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::runtime_error("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
    

      



    test:

    #include <iostream>
    using namespace std;
    
    #include "../include/thread.h"
    using namespace threading;
    
    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();
    	t2.start();
    	t3.start();
    
    	t1.join();
    	t2.join();
    }
    

      

  • 相关阅读:
    第二十次CSP考试有感
    chan数据结构实现原理
    记一次udp端口数据流过程
    Envoy 部署类型
    后K8S时代的微服务
    ESP32-使用有刷直流电机笔记
    ESP32-使用ADC笔记
    网络安全黑白名单设置
    网络安全并发数限制与连接频率限制
    apache与nginx服务器启用https功能
  • 原文地址:https://www.cnblogs.com/aj3423/p/3150502.html
Copyright © 2011-2022 走看看