我不记得 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 最终会删除它。)
等等,让它变得更加复杂。