thread.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 677 行 · 第 1/2 页
CPP
677 行
// Copyright (C) 2001-2003// William E. Kempf// Copyright (C) 2007-8 Anthony Williams//// 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)#include <boost/thread/detail/config.hpp>#include <boost/thread/thread.hpp>#include <boost/thread/xtime.hpp>#include <boost/thread/condition.hpp>#include <boost/thread/locks.hpp>#include <boost/thread/once.hpp>#include <boost/thread/tss.hpp>#ifdef __linux__#include <sys/sysinfo.h>#elif defined(__APPLE__) || defined(__FreeBSD__)#include <sys/types.h>#include <sys/sysctl.h>#elif defined BOOST_HAS_UNISTD_H#include <unistd.h>#endif#include "timeconv.inl"namespace boost{ namespace detail { thread_data_base::~thread_data_base() {} 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 { boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; pthread_key_t current_thread_tls_key; extern "C" { void tls_destructor(void* data) { boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data); if(thread_info) { while(thread_info->tss_data || thread_info->thread_exit_callbacks) { while(thread_info->thread_exit_callbacks) { detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; thread_info->thread_exit_callbacks=current_node->next; if(current_node->func) { (*current_node->func)(); delete current_node->func; } delete current_node; } while(thread_info->tss_data) { detail::tss_data_node* const current_node=thread_info->tss_data; thread_info->tss_data=current_node->next; if(current_node->func) { (*current_node->func)(current_node->value); } delete current_node; } } thread_info->self.reset(); } } } void create_current_thread_tls_key() { BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); } } boost::detail::thread_data_base* get_current_thread_data() { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); return (boost::detail::thread_data_base*)pthread_getspecific(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(!pthread_setspecific(current_thread_tls_key,new_data)); } } namespace { extern "C" { void* thread_proxy(void* param) { boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; thread_info->self.reset(); detail::set_current_thread_data(thread_info.get()); try { thread_info->run(); } catch(thread_interrupted const&) { } catch(...) { std::terminate(); } detail::tls_destructor(thread_info.get()); detail::set_current_thread_data(0); boost::lock_guard<boost::mutex> lock(thread_info->data_mutex); thread_info->done=true; thread_info->done_condition.notify_all(); return 0; } } struct externally_launched_thread: detail::thread_data_base { externally_launched_thread() { interrupt_enabled=false; } void run() {} private: externally_launched_thread(externally_launched_thread&); void operator=(externally_launched_thread&); }; detail::thread_data_base* make_external_thread_data() { detail::thread_data_base* const me(new externally_launched_thread()); me->self.reset(me); set_current_thread_data(me); return me; } detail::thread_data_base* get_or_make_current_thread_data() { detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); if(!current_thread_data) { current_thread_data=make_external_thread_data(); } return current_thread_data; } } thread::thread() {} void thread::start_thread() { thread_info->self=thread_info; int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get()); if (res != 0) { thread_info->self.reset(); throw thread_resource_error(); } } thread::~thread() { detach(); } detail::thread_data_ptr thread::get_thread_info() const { lock_guard<mutex> l(thread_info_mutex); return thread_info; } void thread::join() { detail::thread_data_ptr const local_thread_info=get_thread_info(); if(local_thread_info) { bool do_join=false; { unique_lock<mutex> lock(local_thread_info->data_mutex); while(!local_thread_info->done) { local_thread_info->done_condition.wait(lock); } do_join=!local_thread_info->join_started; if(do_join) { local_thread_info->join_started=true; } else { while(!local_thread_info->joined) { local_thread_info->done_condition.wait(lock); } } } if(do_join) { void* result=0; BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); lock_guard<mutex> lock(local_thread_info->data_mutex); local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } lock_guard<mutex> l1(thread_info_mutex); if(thread_info==local_thread_info) { thread_info.reset(); } } } bool thread::timed_join(system_time const& wait_until) { detail::thread_data_ptr const local_thread_info=get_thread_info(); if(local_thread_info) { bool do_join=false; { unique_lock<mutex> lock(local_thread_info->data_mutex); while(!local_thread_info->done) { if(!local_thread_info->done_condition.timed_wait(lock,wait_until)) { return false; } } do_join=!local_thread_info->join_started; if(do_join) { local_thread_info->join_started=true; } else { while(!local_thread_info->joined) { local_thread_info->done_condition.wait(lock); } } } if(do_join) { void* result=0; BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); lock_guard<mutex> lock(local_thread_info->data_mutex); local_thread_info->joined=true; local_thread_info->done_condition.notify_all(); } lock_guard<mutex> l1(thread_info_mutex); if(thread_info==local_thread_info) { thread_info.reset(); } } return true; } bool thread::joinable() const { return get_thread_info(); } void thread::detach() { detail::thread_data_ptr local_thread_info; { lock_guard<mutex> l1(thread_info_mutex); thread_info.swap(local_thread_info); } if(local_thread_info) { lock_guard<mutex> lock(local_thread_info->data_mutex); if(!local_thread_info->join_started) { BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle)); local_thread_info->join_started=true; local_thread_info->joined=true; } } } namespace this_thread { void sleep(const system_time& st) { detail::thread_data_base* const thread_info=detail::get_current_thread_data(); if(thread_info) { unique_lock<mutex> lk(thread_info->sleep_mutex);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?