Как добавить глупую функцию с аргументами в безумный исполнитель? - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь добавить несколько обычных заданий, которые являются folly :: Function в folly :: ThreadedExecutor.Однако, похоже, что folly :: ThreadedExecutor предоставляет только интерфейс для приема folly::Function<void()>.Как я могу добавить функцию с аргументами и выводами?

// Here's a simple code segment

#include <folly/executors/ThreadedExecutor.h>
#include <folly/futures/Future.h>

int my_func(int t) {
   sleep(t);
   return 1;
}

int main() {
   folly:ThreadedExecutor executor;
   folly:Function<int(int)> job = my_func;
   executor.add(job);  
}

Компилировать с gcc -o folly_executor --std=c++14 -g -O0 -Wall folly_executor.cc -lgtest -lfolly -lpthread -lglog -lgflags -ldl -ldouble-conversion -levent -liberty -lboost_context

Ошибка говорит о несоответствии add прототипа функции в executor и my_func,Ниже приведена ошибка компиляции.

In file included from folly_executor.cc:2:0:
/usr/local/include/folly/executors/ThreadedExecutor.h:67:8: note: 
candidate: virtual void folly::ThreadedExecutor::add(folly::Func)
   void add(Func func) override;
        ^~~
/usr/local/include/folly/executors/ThreadedExecutor.h:67:8: note:   no 
known conversion for argument 1 from 'folly::Function<int(int)>' to 
'folly::Func {aka folly::Function<void()>}'

Интересно, если ограничение добавления прототипа функции имеет необходимую причину.Если нет, то это должен быть правильный способ сделать это.

Кстати, учебник и документ на Github всегда используют folly :: executor с folly: Future.Должен ли я использовать глупость: функция таким образом?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Спасибо за ответ Алекса Бакулина .Я решаю свою проблему с folly::Future интерфейсом, вот мой пример кода.В моем случае я использую Future с AtomicHashMap вместе.Используя Future, можно легко вводить данные и получать доступ к ним с помощью folly::via и std::bind.Однако я все еще не понимаю, почему они сужают использование Folly::Function и ожидают, что оно будет использоваться только для хранения вызываемого объекта без какого-либо ввода и вывода.

#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/futures/Future.h>
#include <folly/AtomicHashMap.h>


folly::Future<int> my_func(int t, folly::AtomicHashMap<int, int>& ahm) {
    ahm.insert(std::make_pair(t, t*2));
    return 1;
}

int main() {
    folly::CPUThreadPoolExecutor executor(8);
    folly::AtomicHashMap<int, int> ahm(4096);
    for (int i = 0; i < 3; i++) {
        folly::Future<int> f = folly::via(&executor, std::bind(my_func, i, std::ref(ahm)));
    }
    executor.join();

    for (int i = 0; i < 3; i++) {
        auto ret = ahm.find((i));
        int r = ret != ahm.end() ? ret->second : 0;
        std::cout << i << "th result is "<< r << std::endl;
    }
    return 0;
}
0 голосов
/ 31 октября 2018

Вы, наверное, уже все выяснили сами, но я приведу ответ только для полноты.ThreadedExectutor - это действительно низкоуровневая вещь, которая просто запускает вещи для вас в отдельных потоках.Когда вы планируете запускать какую-то функцию, вы не контролируете, когда и что она возвращает.Если все, что вам нужно сделать, это заставить вызов функции происходить в отдельном потоке, вы можете заключить этот вызов в анонимную функцию с подписью, которую ожидает исполнитель:

executor.add([]() { my_func(123); });

Если ваша цель также состоит в том, чтобыперехватите вывод вызова, тогда вам будет лучше использовать futures , которые находятся на более высоком уровне абстракции и дают вам гораздо более богатый набор примитивов для работы.

...