一. std::thread类

(一)thread类摘要及分析

class thread { // class for observing and managing threads
public:
    class id;

    using native_handle_type = void*;

    thread() noexcept : _Thr{} { // 创建空的thread对象,实际上线程并未被创建!
    }

private:
    template <class _Tuple, size_t... _Indices>
    static unsigned int __stdcall _Invoke(void* _RawVals) noexcept { // enforces termination
        //接口适配:将用户的可调用对象与_beginthreadex的接口进行适配。

        //子线程重新拥有从主线程转让过来的保存着thread参数副本的tuple堆对象的所有权。
        const unique_ptr<_Tuple> _FnVals(static_cast<_Tuple*>(_RawVals));
        _Tuple& _Tup = *_FnVals;
        _STD invoke(_STD move(_STD get<_Indices>(_Tup))...); //注意,由于tuple中保存的都是副本,因此所有的参数都以右值的方式被转发出去。
        _Cnd_do_broadcast_at_thread_exit(); // TRANSITION, ABI
        return 0;
    }

    template <class _Tuple, size_t... _Indices>
    _NODISCARD static constexpr auto _Get_invoke(
        index_sequence<_Indices...>) noexcept { // select specialization of _Invoke to use
        return &_Invoke<_Tuple, _Indices...>;   //这里返回特化的_Invoke函数指针
    }

public:
    template <class _Fn, class... _Args, class = enable_if_t<!is_same_v<_Remove_cvref_t<_Fn>, thread>>>
    explicit thread(_Fn&& _Fx, _Args&& ... _Ax) { // construct with _Fx(_Ax...)
        using _Tuple                 = tuple<decay_t<_Fn>, decay_t<_Args>...>; //将传入thread的所有参数保存着tuple

        //在堆上创建tuple以按值保存thread所有参数的副本,指针用unique_ptr来管理。
        auto _Decay_copied = _STD make_unique<_Tuple>(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); //创建tuple的智能指针
        constexpr auto _Invoker_proc = _Get_invoke<_Tuple>(make_index_sequence<1 + sizeof...(_Args)>{}); //获取线程函数地址

        //在Windows系统中,会调用_beginthredex来创建新线程。其中,_Invoker_proc为线程函数地址,它要求的参数为tuple的指针,即_Decay_copied.get()
        //注意:线程创建后即立即运行(第5个参数为0),原生的线程id保存在_Thr._Id中,句柄保存在_Thr._Hnd。
        _Thr._Hnd =
            reinterpret_cast<void*>(_CSTD _beginthreadex(nullptr, 0, _Invoker_proc, _Decay_copied.get(), 0, &_Thr._Id));
        if (_Thr._Hnd == nullptr) { // failed to start thread
            _Thr._Id = 0;
            _Throw_Cpp_error(_RESOURCE_UNAVAILABLE_TRY_AGAIN);
        }
        else { // ownership transferred to the thread
            (void)_Decay_copied.release(); //转让tuple的所有权给新的线程。
        }
    }

    ~thread() noexcept { // clean up
        if (joinable()) {  //注意,std::thread析构时,如果线程仍可joinable,则会调用terminate终止程序!
            _STD terminate();
        }
    }

    thread(thread&& _Other) noexcept : _Thr(_STD exchange(_Other._Thr, {})) { // move from _Other
    }

    thread& operator=(thread&& _Other) noexcept { // move from _Other

        if (joinable()) {
            _STD terminate();
        }

        _Thr = _STD exchange(_Other._Thr, {});
        return *this;
    }

    thread(const thread&) = delete;    //thread对象不能被复制
    thread& operator=(const thread&) = delete; //thread对象不能被拷贝赋值

    void swap(thread& _Other) noexcept { // swap with _Other
        _STD swap(_Thr, _Other._Thr);
    }

    _NODISCARD bool joinable() const noexcept { // return true if this thread can be joined
        return _Thr._Id != 0; //原生的线程id不为0,表示底层的线程己经创建
    }

    void join() { // join thread
        if (!joinable()) {
            _Throw_Cpp_error(_INVALID_ARGUMENT);
        }

        if (_Thr._Id == _Thrd_id()) {
            _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
        }

        if (_Thrd_join(_Thr, nullptr) != _Thrd_success) {
            _Throw_Cpp_error(_NO_SUCH_PROCESS);
        }

        _Thr = {}; //注意调用join以后,原生线程id被清零,意味着join只能被调用一次!
    }

    void detach() { // detach thread
        if (!joinable()) {
            _Throw_Cpp_error(_INVALID_ARGUMENT);
        }

        _Check_C_return(_Thrd_detach(_Thr)); //线程被分离,成为后台线程
        _Thr = {};  //注意调用detach以后,原生线程id被清零,意味着detach也只能被调用一次!
    }

    _NODISCARD id get_id() const noexcept;

    _NODISCARD static unsigned int hardware_concurrency() noexcept { // return number of hardware thread contexts
        return _Thrd_hardware_concurrency();
    }

    _NODISCARD native_handle_type native_handle() { // return Win32 HANDLE as void *
        return _Thr._Hnd;
    }

private:
    _Thrd_t _Thr;
};
std::thread类摘要

相关文章:

  • 2021-11-27
  • 2021-11-11
  • 2022-12-23
  • 2023-01-08
  • 2022-12-23
  • 2022-12-23
  • 2022-01-08
  • 2021-10-01
猜你喜欢
  • 2021-08-09
  • 2021-11-17
  • 2022-12-23
  • 2021-05-24
  • 2021-06-03
  • 2021-10-30
相关资源
相似解决方案