thread.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 596 行 · 第 1/2 页
CPP
596 行
// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)// (C) Copyright 2007 Anthony Williams// (C) Copyright 2007 David Deakins#define _WIN32_WINNT 0x400#define WINVER 0x400#include <boost/thread/thread.hpp>#include <algorithm>#include <windows.h>#ifndef UNDER_CE#include <process.h>#endif#include <stdio.h>#include <boost/thread/once.hpp>#include <boost/thread/tss.hpp>#include <boost/assert.hpp>#include <boost/thread/detail/tss_hooks.hpp>#include <boost/date_time/posix_time/conversion.hpp>namespace boost{ namespace { boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; DWORD current_thread_tls_key=0; void create_current_thread_tls_key() { tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in current_thread_tls_key=TlsAlloc(); BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES); } void cleanup_tls_key() { if(current_thread_tls_key) { TlsFree(current_thread_tls_key); current_thread_tls_key=0; } } detail::thread_data_base* get_current_thread_data() { if(!current_thread_tls_key) { return 0; } return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); } void set_current_thread_data(detail::thread_data_base* new_data) { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); }#ifdef BOOST_NO_THREADEX// Windows CE doesn't define _beginthreadex struct ThreadProxyData { typedef unsigned (__stdcall* func)(void*); func start_address_; void* arglist_; ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {} }; DWORD WINAPI ThreadProxy(LPVOID args) { ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args); DWORD ret=data->start_address_(data->arglist_); delete data; return ret; } typedef void* uintptr_t; inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), void* arglist, unsigned initflag, unsigned* thrdaddr) { DWORD threadID; HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy, new ThreadProxyData(start_address,arglist),initflag,&threadID); if (hthread!=0) *thrdaddr=threadID; return reinterpret_cast<uintptr_t const>(hthread); }#endif } namespace detail { struct thread_exit_callback_node { boost::detail::thread_exit_function_base* func; thread_exit_callback_node* next; thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, thread_exit_callback_node* next_): func(func_),next(next_) {} }; struct tss_data_node { void const* key; boost::shared_ptr<boost::detail::tss_cleanup_function> func; void* value; tss_data_node* next; tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_, tss_data_node* next_): key(key_),func(func_),value(value_),next(next_) {} }; } namespace { void run_thread_exit_callbacks() { detail::thread_data_ptr current_thread_data(get_current_thread_data(),false); if(current_thread_data) { while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks) { while(current_thread_data->thread_exit_callbacks) { detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; current_thread_data->thread_exit_callbacks=current_node->next; if(current_node->func) { (*current_node->func)(); boost::detail::heap_delete(current_node->func); } boost::detail::heap_delete(current_node); } while(current_thread_data->tss_data) { detail::tss_data_node* const current_node=current_thread_data->tss_data; current_thread_data->tss_data=current_node->next; if(current_node->func) { (*current_node->func)(current_node->value); } boost::detail::heap_delete(current_node); } } set_current_thread_data(0); } } unsigned __stdcall thread_start_function(void* param) { detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); set_current_thread_data(thread_info); try { thread_info->run(); } catch(thread_interrupted const&) { } catch(...) { std::terminate(); } run_thread_exit_callbacks(); return 0; } } thread::thread() {} void thread::start_thread() { uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { throw thread_resource_error(); } intrusive_ptr_add_ref(thread_info.get()); thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); } thread::thread(detail::thread_data_ptr data): thread_info(data) {} namespace { struct externally_launched_thread: detail::thread_data_base { externally_launched_thread() { ++count; interruption_enabled=false; } void run() {} private: externally_launched_thread(externally_launched_thread&); void operator=(externally_launched_thread&); }; void make_external_thread_data() { externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); set_current_thread_data(me); } detail::thread_data_base* get_or_make_current_thread_data() { detail::thread_data_base* current_thread_data(get_current_thread_data()); if(!current_thread_data) { make_external_thread_data(); current_thread_data=get_current_thread_data(); } return current_thread_data; } } thread::~thread() { detach(); } thread::id thread::get_id() const { return thread::id(get_thread_info()); } bool thread::joinable() const { return get_thread_info(); } void thread::join() { detail::thread_data_ptr local_thread_info=get_thread_info(); if(local_thread_info) { this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel()); release_handle(); } } bool thread::timed_join(boost::system_time const& wait_until) { detail::thread_data_ptr local_thread_info=get_thread_info(); if(local_thread_info) { if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until))) { return false; } release_handle(); } return true; } void thread::detach() { release_handle(); } void thread::release_handle() { lock_guard<mutex> l1(thread_info_mutex); thread_info=0; } void thread::interrupt() { detail::thread_data_ptr local_thread_info=get_thread_info(); if(local_thread_info) { local_thread_info->interrupt(); } } bool thread::interruption_requested() const { detail::thread_data_ptr local_thread_info=get_thread_info();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?