将可变参数模板传递给pthread_create

时间:2018-10-23 08:20:26

标签: c++ multithreading c++11

我知道pthread_create接受一个void*(*)(void*)参数和一个void*,因此我进行了2次(失败的)尝试包装函数和Args ...:

a。创建一个C样式的void *run(void*)函数,该函数将调用传递给它的std::function对象:

class thread
{
public:
    typedef std::function<void()> functor_t;

    static void* run(void* f) 
    {
        functor_t* functor = (functor_t*)f;
        (*functor)();
        delete functor;
        return nullptr;
    }

    template<typename Callable, typename... Args>
    explicit thread(size_t stack_size, Callable && callable, Args&&... args) {
        auto task_ptr = std::make_shared<std::packaged_task<decltype(callable(args...))()>>(
            std::bind(std::forward<Callable>(callable), std::placeholders::_1, std::forward<Args>(args)...)
            );
        functor_t* functor = new functor_t([task_ptr]() {
            (*task_ptr)();
        });

        pthread_attr_t attr = { 0};
        if (pthread_attr_init(&attr) == 0)
        {
            m_joinable = pthread_attr_setstacksize(&attr, stack_size) == 0 &&
                         pthread_create(&m_id, &attr, &run, functor);
            pthread_attr_destroy(&attr);
        }
    }
private:
    pthread_t   m_id        = -1    ;
    bool        m_joinable  = false ;
};

这会在GCC 4.8.5中导致以下错误:

  

/ usr / include / c ++ / 4.8.2 / functional:实例化struct   std :: _ Bind_simple(std :: _ Placeholder <1>,int))(int *)>>()>’:   /usr/include/c++/4.8.2/future:1284:55:从'void必需   std :: __ future_base :: _ Task_state <_Fn,_Alloc,_Res(_Args   ...)> :: _ M_run(_Args ...)[with _Fn = std :: _ Bind(std :: _ Placeholder <1>,int))(int *)>; _Alloc = std :: allocator;   _Res = void; _Args = {}]’thread.cpp:17:1:此处需要/usr/include/c++/4.8.2/functional:1697:61:错误:没有名为“ type”的类型   在“ class std :: result_of(std :: _ Placeholder <1>,int))(int *)>>()>”中          typedef类型名result_of <_Callable(_Args ...)> :: type result_type;                                                                ^ /usr/include/c++/4.8.2/functional:1727:9:错误:没有名为“ type”的类型   在“ class std :: result_of(std :: _ Placeholder <1>,int))(int *)>>()>”中            _M_invoke(_Index_tuple <_Indices ...>)            ^

b。按照此示例http://coliru.stacked-crooked.com/a/a6c607514601b013

class thread
{
public:
    template< typename Callable, typename... Args >
    explicit thread(size_t stack_size, Callable&& callable, Args&&... args )
    {
        auto l = new auto([=]{ callable(args...); });
        auto te = [](void* rp) -> void*
        {
            auto p = reinterpret_cast<decltype(l)>(rp);
            (*p)();
            delete p;
            return nullptr;
        };
        pthread_attr_t attr = { 0};
        if (pthread_attr_init(&attr) == 0)
        {
            m_joinable = pthread_attr_setstacksize(&attr, stack_size) == 0 &&
                         pthread_create(&m_id, &attr, te, l);
            pthread_attr_destroy(&attr);
        }
    }
private:
    pthread_t   m_id        = -1    ;
    bool        m_joinable  = false ;
};

这应该可以在clang中使用,但在GCC 4.8.5中使用以下方法会失败:

  

在thread.cpp包含的文件中:2:0:   thread.h:在lambda函数中:   thread.h:82:37:错误:参数   没有以“ ...”扩展的包:        自动l =新自动([=] {callable(args ...);});                                        ^ thread.h:82:37:注意:
  “ args”线程。h:82:41:错误:   扩展模式“ args”不包含任何参数包        自动l =新自动([=] {callable(args ...);});                                            ^ thread.h:在实例化   ‘struct thread :: thread(size_t,Callable &&,Args && ...)[   Callable = void()(int ); Args = {int *}; size_t =长无符号   int] :: __ lambda4’:thread.h:82:48:
  必须来自‘thread :: thread(size_t,Callable &&,Args && ...)   [with Callable = void()(int ); Args = {int *}; size_t =长无符号   int]’thread.cpp:14:32:从此处开始   thread.h:82:37:错误:使用   无效字段‘thread :: thread(size_t,Callable &&,Args &&   ...):: ____ lambda4 :: __ args’        自动l =新自动([=] {callable(args ...);});                                        ^ thread.h:83:被先前版本所混淆   错误,救助

两者都跟着下面的主管跑了:

int g=5;

void run(int *i)
{
    printf("t\n");
}

int main()
{

    gs_thread t(256*1024, &run, &g);
    printf("m\n");
    t.join();
}

1 个答案:

答案 0 :(得分:1)

如果从第一个版本中删除std::placeholders::_1,,它将使用gcc进行编译。