如何为线程池编写类型化包装器?

问题描述 投票:0回答:1

我有一个简单的线程池。它获取任务并使用循环法在线程之间分配它们。 任务看起来像这样

using TaskFn = void (*)(void*);

struct Task {
    TaskFn fn;
    void* args;
};

只有两个指针:指向接受

void*
的函数和指向参数本身。线程池调用
Task::fn
并传递
Task::args
。一切都运转良好。

但是我想为整个事情编写一个类型化包装器。所以我可以这样写:

Task some_task = MakeTask([](int a, int b){
        // Task body
}, 123, 456);

我不需要关闭来工作。我写的代码无法编译:

template <typename Function, typename ... Args>
void DoCall(Function f, std::tuple<Args...>* args) {
    auto callable = [args, f](){
        std::apply(f, *args);
    };
    callable();
}

template <typename Function, typename ... Args>
Task MakeTask(Function f, Args ... args) {
    Task task;
             
    std::tuple<Args...>* args_on_heap = new std::tuple<Args...>(args...);
    task.args = (void*) args_on_heap;

    TaskFn fn = [](void* ptr){
        // The problem here is that I can’t pass `f` here without creating a closure.
        // But if I create a closure, the signature will be different. 
        // In theory, everything that is needed is known at the compilation stage. 
        // But how to curb the compiler?
        DoCall<Function, Args...>(f, (std::tuple<Args...>*) ptr);
    };

    task.fn = fn;
    return task;
    
    // P.S I know that args_on_heap leaks.
}

所以,问题:

  1. 我的想法可以实现吗?
  2. 如果是,该怎么做?我应该往什么方向挖?该语言的哪些功能(我可能还不知道)将帮助我实现我的想法。
  3. 如果我无法实现这一点,那么还有什么替代方案?

提前谢谢您:)

c++ templates lambda metaprogramming functor
1个回答
0
投票

捕获 lambda 可以存储在 std::function 中,并且为了防止参数泄漏,您应该使用 std::shared_ptr

#include <functional>
#include <memory>

struct Task {
    std::function<void(void*)> fn;
    std::shared_ptr<void> args;
};

template <typename Function, typename ... Args>
void DoCall(Function f, std::tuple<Args...>* args) {
    auto callable = [args, f](){
        std::apply(f, *args);
    };
    callable();
}

template <typename Function, typename ... Args>
Task MakeTask(Function f, Args ... args) {
    Task task;
             
    task.args = std::make_shared<std::tuple<Args...>>(args...);

    task.fn = [f](void* ptr){

        DoCall<Function, Args...>(f, (std::tuple<Args...>*) ptr);
    };

    return task;
    
}
© www.soinside.com 2019 - 2024. All rights reserved.