将参数传递给pthread_create的通用方法(使用带有2个压缩参数列表的可变参数模板函数)

时间:2014-08-14 16:48:01

标签: c++ templates c++11 pthreads variadic-templates

我正在尝试实现一个thread类,因为我自己定义了C ++ 11标准,因为我发现这是一个使用可变参数模板和C ++语言的其他高级功能的好方法。

据我所知,在使用 pthreads 库时,在创建线程时,分配给它的函数必须具有以下签名:void* method(void* param)

pthread_create的第四个参数只允许传递一个参数。 在Internet上搜索,传递多个参数的最常用方法是将它们打包在一个结构中,并将该结构上的指针作为参数传递。

因为C ++ thread类允许函数具有我们想要的参数,所以我查看了LLVM实现(肯定接近其他实现)并看到它们使用了代理函数,这对我来说似乎是最好的方式。

因为我不想使用forwarddecay(它为LLVM制作的方式),如果可能的话,使它与众不同,因为复制/粘贴不会让我学到任何东西,我虽然可以使用可变模板函数作为代理。

以下是我的想法:

/** THREAD CLASS **/
template <typename _ret_type, typename... _args_types>
void*
__thread_proxy(void* p)
{
    _ret_type(*fn)(_args_types...) = reinterpret_cast<_ret_type(*)(_args_types...)>(p);
    std::cout << "Thread " << pthread_self() << " speaking! :)" << std::endl;
    fn(6, 'a');
    return bk::null_pointer;
}

class thread
{
    pthread_t _tid;

public:
    thread() :
    _tid(0)
    { }

    template <typename ret_type, typename... args_types>
    thread(ret_type(*fn)(args_types...), args_types... args)
    {
        pthread_create(&_tid, 0, __thread_proxy<ret_type, args_types...>, &fn);
    }
}

/** USAGE **/
void
test(int i, char c)
{
    std::cout << "test: ";
    while (i > 0) {
        std::cout << c;
        i--;
    }
    std::cout << std::endl;
}

int main(const int argc, const char** argv)
{
    thread t(test, 6, 'a');
}

正如您所看到的,我此时无法传递参数,这就是为什么在__thread_proxy函数中,我直接使用参数调用fn。 我已经使用pthread_create的第四个参数来传递线程的入口点。因为入口点返回类型和参数类型作为模板参数传递,我虽然可以对参数做同样的事情。

然后我将代理代码修改为:

template <typename _ret_type, typename... _args_types, _args_types... args_values>
void*
__thread_proxy(void* p)
{
    _ret_type(*fn)(_args_types...) = reinterpret_cast<_ret_type(*)(_args_types...)>(p);
    std::cout << "Thread " << pthread_self() << " speaking! :)" << std::endl;
    fn(args_values...);
    return bk::null_pointer;
}

这里的问题是,即使尝试像这样__thread_proxy<ret_type, args_types..., args...>(&fn)(来自线程的第二个构造函数)调用代理,也会返回以下错误:

  
    

没有用于调用'__thread_proxy'的匹配函数
    忽略候选模板:模板参数'_args_types'

的显式指定参数无效   

我从未见过这种消息,但是尝试自己解决这个问题至少4个小时,我认为问题在于,当花费参数包时,模板参数为__thread_proxy<void, int, char, 6, 'a'>。看到这一点,我想我可以说编译器无法知道_args_types的结束位置和args_values的开始位置。

我指望你的灯光。我不是模板的新手,但我不是很常见,所以你给我的每一个资源,欢迎给我的提示。
- 提前致谢

0 个答案:

没有答案