Я пытаюсь добавить несколько нормальных заданий, которые являются 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. Должен ли я использовать глупость: функция таким образом?
Вы, наверное, уже все выяснили сами, но я приведу ответ только для полноты. ThreadedExectutor
это действительно низкоуровневая вещь, которая просто запускает вещи для вас в отдельных потоках. Когда вы планируете запускать какую-то функцию, вы не контролируете, когда и что она возвращает. Если все, что вам нужно сделать, это сделать вызов функции в отдельном потоке, вы можете заключить этот вызов в анонимную функцию с подписью, которую ожидает исполнитель:
executor.add([]() { my_func(123); });
Если ваша цель также состоит в том, чтобы захватить результат вызова, то вам будет лучше использовать фьючерсы, которые находятся на более высоком уровне абстракции и дают вам гораздо более богатый набор примитивов для работы.
Спасибо за Алексея Бакулина ответ. Я решаю свою проблему с 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;
}