【问题标题】:Passing variadic template to pthread_create将可变参数模板传递给 pthread_create
【发布时间】:2019-03-27 09:53:04
【问题描述】:

我知道pthread_create 接受void*(*)(void*) 参数和void*,所以我进行了2 次(失败)尝试包装函数和参数...:

一个。创建一个 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, int))(int*)> >()>': /usr/include/c++/4.8.2/future:1284:55: 需要来自‘void std::__future_base::_Task_state<_fn _alloc _res ...>::_M_run(_Args ...) [with _Fn = std::_Bind(std::_Placeholder, int))(int*)>; _Alloc = std::allocator; _Res = 无效; _Args = {}]' thread.cpp:17:1:从这里需要 /usr/include/c++/4.8.2/functional:1697:61:错误:没有名为“type”的类型 在'类 std::result_of(std::_Placeholder, int))(int*)> >()>' typedef typename result_of<_callable>::type result_type; ^ /usr/include/c++/4.8.2/functional:1727:9:错误:没有名为“type”的类型 在'类 std::result_of(std::_Placeholder, 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:错误:参数 未使用“...”扩展的包: auto l = new auto([=]{ callable(args...); }); ^ thread.h:82:37: 注意:
‘args’ thread.h:82:41: 错误: 扩展模式“args”不包含参数包 auto l = new auto([=]{ callable(args...); }); ^ thread.h:在实例化 'struct thread::thread(size_t, Callable&&, Args&& ...) [with Callable = void ()(int);参数 = {int*}; size_t = 长无符号 int]::__lambda4': thread.h:82:48:
来自‘thread::thread(size_t, Callable&&, Args&& ...) [with Callable = void ()(int);参数 = {int*}; size_t = 长无符号 int]' thread.cpp:14:32: 从这里需要 thread.h:82:37:错误:使用 无效字段'thread::thread(size_t, Callable&&, Args&& ...)::__lambda4::__args’ auto l = new auto([=]{ 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();
}

【问题讨论】:

  • 也许可以尝试将this 作为run 的参数传递,然后您基本上可以调用您喜欢的任何方法。不会是最好的解决方案,但比你目前拥有的更简单
  • 一个问题可能是您使用的是非常旧的 GCC 版本,并且对 C++11 的支持不完整。如果可能,请尝试使用较新版本的 GCC。
  • 使用 std::thread 而不是 pthreads API。
  • 关于 [a] 案例,当您的绑定对象在没有参数的情况下被调用时,您为什么要将 std::placeholders::_1 传递给绑定函数?删除它,您的代码就会编译。
  • 在您的第二次尝试中,修复是auto l = new auto([&amp;callable, args...]{ callable(args...); }); 当然,您必须确保callable 在使用之前不会消失。这适用于两种尝试。 IMNSHO 可调用对象应始终按值 传递。此外,m_joinable 设置不正确,因为pthread_create 成功返回 0 ;)

标签: c++ multithreading c++11


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2014-10-20
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2011-11-15
    • 2017-07-08
    • 2022-01-01
    相关资源
    最近更新 更多