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 + -
显示快捷键?