内容纲要

vc2012 thread_local __declspec(thread)

https://docs.microsoft.com/en-us/cpp/c-language/thread-local-storage?view=vs-2019
https://cn.bing.com/images/search?view=detailV2&ccid=pbGFCv0z&id=85EE8BE9F831A064143D7558BCCB43C3EF6FD534&thid=OIP.pbGFCv0zN3hVmpcybT53XAEgDY&mediaurl=https%3a%2f%2fimage.slidesharecdn.com%2fvisualcc11-130825104748-phpapp02%2f95%2fvisual-cc11-36-638.jpg%3fcb%3d1377427901&exph=479&expw=638&q=vc2012+thread_local+__declspec+thread&simid=608053667667838274&selectedIndex=2&qpvt=vc2012+thread_local+__declspec+thread&ajaxhist=0

https://www.modernescpp.com/index.php/a-new-thread-with-c-20-std-jthread

https://www.howtobuildsoftware.com/index.php/how-do/c2dC/c-11-concurrency-c-standard-library-why-stdthread-doesnt-have-try-join-for-and-interrupt-methods

https://thispointer.com/c11-how-to-stop-or-terminate-a-thread/

vs2012 下适用

class StoppableThread
{

public:

    StoppableThread(int term_wait_seconds = 3) : thread_handle_(NULL), stop_event_(NULL), running_event_(NULL), running_(FALSE), thread_ptr_(nullptr), term_wait_seconds_(term_wait_seconds)
    {
    }

    virtual ~StoppableThread()
    {
        Stop();
    }

    enum { Running = 1, Shutdown, Error };

    int Wait()
    {
        HANDLE handles[2] = { stop_event_, running_event_ };

        switch (::WaitForMultipleObjects(2, handles, FALSE, INFINITE)) {
        case WAIT_OBJECT_0:
            return Shutdown;

        case WAIT_OBJECT_0 + 1:
            return Running;
        }

        return Error;
    }

    template<class F>
    auto Start(F&& f) -> std::future<typename std::result_of<F()>::type> {
        typedef std::result_of<F()>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1>
    auto Start(F&& f, A1&& a1) -> std::future<typename std::result_of<F(A1)>::type> {
        typedef std::result_of<F(A1)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2>
    auto Start(F&& f, A1&& a1, A2&& a2) -> std::future<typename std::result_of<F(A1, A2)>::type> {
        typedef std::result_of<F(A1, A2)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3) -> std::future<typename std::result_of<F(A1, A2, A3)>::type> {
        typedef std::result_of<F(A1, A2, A3)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4) -> std::future<typename std::result_of<F(A1, A2, A3, A4)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4, class A5>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5) -> std::future<typename std::result_of<F(A1, A2, A3, A4, A5)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4, A5)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4, class A5, class A6>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6) -> std::future<typename std::result_of<F(A1, A2, A3, A4, A5, A6)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4, A5, A6)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7) -> std::future<typename std::result_of<F(A1, A2, A3, A4, A5, A6, A7)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4, A5, A6, A7)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8) -> std::future<typename std::result_of<F(A1, A2, A3, A4, A5, A6, A7, A8)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4, A5, A6, A7, A8)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8))
        );

        STOPPABLE_THREAD_START_RET;
    }

    template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
    auto Start(F&& f, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9) -> std::future<typename std::result_of<F(A1, A2, A3, A4, A5, A6, A7, A8, A9)>::type> {
        typedef std::result_of<F(A1, A2, A3, A4, A5, A6, A7, A8, A9)>::type return_type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8), std::forward<A8>(a9))
        );

        STOPPABLE_THREAD_START_RET;
    }

    /*template<class F, class... Args>
    auto Start(F&& f, Args&&... args)
    {
        using return_type = typename std::result_of<F(Args...)>::type;
        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
            );
        auto result = task->get_future();
        running_ = FALSE;

        if (CreateEvents()) {
            thread_ptr_.reset(new std::thread(std::move(*task)));
            thread_handle_ = (HANDLE)thread_ptr_->native_handle();

            if (thread_ptr_ && thread_ptr_->joinable())
                running_ = TRUE;
            else
                thread_handle_ = NULL;
        }

        return result;
    }*/

    void Stop()
    {
        if (running_ && thread_ptr_ && thread_ptr_->joinable()) {
            SetEvent(stop_event_);

            //::WaitForSingleObject(thread_handle_, INFINITE);

            // 等待 3 秒后杀死
            if (WaitForSingleObject(thread_handle_, term_wait_seconds_) == WAIT_TIMEOUT)
                TerminateThread(thread_handle_, 1L);

            thread_ptr_->detach();
            //::CloseHandle(thread_handle_);
            ResetEvent(stop_event_);
            thread_handle_ = NULL;
        }

        running_ = FALSE;
    }

    inline void Pause()
    {
        if (running_)
            ResetEvent(running_event_);
    }

    inline void Run()
    {
        if (running_)
            SetEvent(running_event_);
    }

    inline bool IsRunning()
    {
        //return running_;
        return thread_ptr_->joinable();
    }

protected:

    bool CreateEvents()
    {
        stop_event_ = CreateEventA(NULL, TRUE, FALSE, NULL);
        running_event_ = CreateEventA(NULL, TRUE, TRUE, NULL);
        return GetLastError() == 0;
    }

    HANDLE      stop_event_;
    HANDLE      running_event_;
    HANDLE      thread_handle_;
    bool        running_;
    std::function<void()> callback_;
    std::unique_ptr<std::thread> thread_ptr_;
    int         term_wait_seconds_;
};

发表评论

电子邮件地址不会被公开。 必填项已用*标注