Расширение многопоточной системы Job / Worker в C ++ - PullRequest
2 голосов
/ 18 октября 2019

Я читал учебное пособие Бена Хоффмана (https://benhoffman.tech/cpp/general/2018/11/13/cpp-job-system.html)

) Я пытался собрать вместе версию имеющейся у него системы Job / Worker, но вместо использования void*для аргументов, приводящих затем к известной структуре, я пытался использовать переменные аргументы. Идея состоит в том, что задание получает «родителя» для выполнения метода, указатель функции на указанный метод и Args... дляаргумент (ы). Однако, я получаю внутреннюю ошибку компилятора, если я пытаюсь построить. Вот класс задания:

template <class T, typename... Args>
struct JobMemberFunc : IJob
{
    JobMemberFunc(T* aParent, void (T::* f)(Args...), Args... Args)
    {
        parentObj = aParent;
        func_ptr = f;
        saved_args = ::std::make_tuple (::std::move(Args)...);
    }

    virtual bool invoke() override
    {
        if (!parentObj) { return false; }

        (parentObj->*func_ptr)(::std::move(saved_args));
        return true;
    }

    /** the object to invoke the function pointer on */
    T* parentObj;

    /** The function pointer to call when we invoke this function */
    void (T::* func_ptr)(Args...);

    ::std::tuple<Args...> saved_args;
};


struct CpuJob
{
    IJob* jobPtr = nullptr;
};

Тогда есть метод AddJob, где внутренняя ошибка компилятора фактически происходит.

template <typename T, typename... Args>
void AddJob(T* aParent, void(T::* func_ptr)(Args...), Args... args)
{//This curly bracket is where the internal compiler error happens
    CpuJob aJob = {};

    JobMemberFunc<T, Args...>* jobPtr = new JobMemberFunc<T, Args...>(aParent, func_ptr, 
    std::forward<Args>(args)...);

    aJob.jobPtr = jobPtr;

    locklessReadyQueue.enqueue(aJob);
}

Более чем рад, что мне все равно говорят, что это плохой / неправильный способ попытаться сделать это. Я думал о том, чтобы покончить с этим и иметь стандартизированный список аргументов или сделать что-то полиморфное, но я действительнохочу сделать эту работу, чтобы я мог буквально попросить систему работы делать все, что мне нравится.

Спасибо!

1 Ответ

2 голосов
/ 18 октября 2019

std::function<void()> (в сочетании с лямбдами) уже делают то, что вы пытаетесь сделать с JobMemberFunc.

void AddJob(std::function<void()>&& job)
{
    locklessReadyQueue.enqueue(std::move(job));
}

С этим вы можете отправить любой вызов функции какзадание.

Например, вызов some_obj.some_method(some_arg) становится:

  AddJob([&] { some_obj.some_method(some_arg); });

Нет более уродливых указателей на элементы ...

Вы можете найти большеПримеры полного объединения потоков здесь: Объединение потоков в C ++ 11

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...