创建复制传递给它们的参数的线程

时间:2010-08-16 22:17:03

标签: c++ c pthreads

我目前正在使用boost :: thread,因为它非常方便地允许我将任意数量的参数传递给线程并沿途复制它们,所以我不必担心它们会在之前被删除线程启动。是否有其他库允许这样,或者使用pthreads模拟它?我想让自己脱离提升,但我从未见过任何其他图书馆这样做。

2 个答案:

答案 0 :(得分:1)

我不记得Boost.Thread的细节,但总的想法是这样的:

class thread_function_base
{
public:
    virtual ~thread_function_base(void) {}
    virtual void run(void) = 0;
};

template <typename Func>
class thread_function_0 : public thread_function_base
{
public:
    thread_function_0(const Func& pFunc) :
    mFunc(pFunc)
    {}

    void run(void)
    {
        mFunc();
    }

private:
    Func mFunc;
};

template <typename Func, typename A0>
class thread_function_1 : public thread_function_base
{
public:
    thread_function_1(const Func& pFunc, const A0& pA0) :
    mFunc(pFunc),
    mA0(pA0)
    {}

    void run(void)
    {
        mFunc(mA0);
    }

private:
    Func mFunc;
    A0 mA0;
};

// and so on to some limit, either
// generated either by hand (yuck), by
// Boost.PP (phew), or by C++0x's
// variadic templates (yay, no limit either)

class thread
{
public:
    template <typename Func>
    thread(const Func& pFunc)
    {
        std::auto_ptr<thread_function_base>
            threadFunc(new thread_function_0<Func>(pFunc));

        create_thread(threadFunc);
    }

    template <typename Func, typename A0>
    thread(const Func& pFunc, const A0& pA0)
    {
        std::auto_ptr<thread_function_base>
            threadFunc(new thread_function_1<Func, A0>(pFunc, pA0));

        create_thread(threadFunc);
    }

    // again, needs to be generated somehow

private:
    // noncopyable
    thread(const thread&);
    thread& operator=(const thread&);

    // signature needs to match implementations expectations:
    static void thread_function(void* pUserData)
    {
        std::auto_ptr<thread_function_base>
            pFunc(static_cast<thread_function_base*>(pUserData));

        // (A)

        pFunc->run();
    }

    void create_thread(std::auto_ptr<thread_function_base>& pThreadFunc)
    {
        // again, implementation specific function:
        if (create_thread(&thread_function, pThreadFunc.get(), ...))
        {
            // failed, do something (and return), 
            // auto_ptr in constructor will free resources
            return;
        }    

        // thread was created, so it now owns that resource
        pThreadFunc.release();

        // (B)
    }
};

基本上,调用线程所需的一切都被复制到一些动态分配的容器中,一个指向该动态容器的指针被传递到线程函数(平凡),然后所有权从线程外部传递到内部。

您不仅可以将thread_function_base打包到用户数据中,还可以将({特定于实现的)信号句柄打包,从而使事情变得更安全。线程函数将在(A)处阻塞,直到信号在(B)处被引发,表明主线程已经为工作线程提供了资源的完全所有权。 (从那里auto_ptr将最终删除它。)

等等,让它更复杂。

答案 1 :(得分:0)

您必须在pthread_create周围创建一个包装器,并将特定于线程的存储传递给包含参数数组的pthread_create。包装器将使用如下形式:

void *mythreadfunction(void *arg) {...}

pthread_create_wrapper(context ctx, ...) {
   Array *arr;
   pthread_t mythread;

   arr = new Array();

   // push arguments to array here
   blah blah ...
   // create thread and pass in argument list as thread data pointer.
   pthread_create(&mythread, NULL, mythreadfunction, (void *)arr);
}