読者です 読者をやめる 読者になる 読者になる

Boost.Threadの中でやってること - Windows編

C++

Boost.ThreadがC APIにどうやって関数オブジェクトを渡してるのか気になったので読んでました。
以下、Boost.ThreadがWindows上でやってることの簡易実装です。

#include <windows.h>
#include <process.h>
#include <iostream>
#include <boost/function.hpp>

class thread_data_base {
public:
    HANDLE thread_handle;
    virtual void run() = 0;

    void join()
    {
        WaitForSingleObject(thread_handle, INFINITE);
        CloseHandle(thread_handle);
    }
};

class thread_data : public thread_data_base {
    boost::function<void()> f_;
public:
    template <class F>
    void set_functor(F f)
    {
        f_ = f;
    }

    void run()
    {
        f_();
    }
};

// スレッドで実行される関数
unsigned __stdcall thread_start_function(void* param)
{
    thread_data_base* thread_info = reinterpret_cast<thread_data_base*>(param); // 元の型に戻す
    thread_info->run(); // 実際の関数オブジェクトを呼び出す

    return 0;
}

void start_thread(thread_data_base& t)
{
    unsigned int thread_id = 0; // てきとう

    // スレッド起動
    t.thread_handle = (HANDLE)_beginthreadex(
                                0,
                                0,
                                &thread_start_function,
                                &t, // パラメータで関数オブジェクト(を含むデータを渡す)
                                CREATE_SUSPENDED,
                                &thread_id);

    ResumeThread(t.thread_handle);
}

// スレッドで動かす関数オブジェクト
struct functor {
    void operator()()
    {
        std::cout << "processing thread..." << std::endl;
    }
};

int main()
{
    thread_data t;
    t.set_functor(functor());

    start_thread(t);

    t.join();
}
processing thread...

やってることは単に、関数オブジェクトをスレッドのパラメータとしてvoid*にして渡し、スレッドの中で元の型に戻して呼んでるだけでした。