Folly's Fibers
предоставляет нам специальную реализацию Promise
, а Future
уже подходит для оптоволокна.Однако этот специальный Promise
не предоставляет пользователю метод getFuture
, который, по крайней мере в моем случае, делает Promise
непригодным для использования.Вопрос в том, будет ли глупость «общего назначения» Promise
работать в волокнах?
И я собрал простой тест, чтобы проверить его эмпирически.
#include <chrono>
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <folly/futures/Future.h>
#include <folly/fibers/AddTasks.h>
#include <folly/fibers/EventBaseLoopController.h>
namespace ff = folly::fibers;
using namespace std::chrono_literals;
TEST(FiberManager, addTasksNoncopyable)
{
std::atomic_size_t counter = 0;
folly::Promise<int> promise;
auto future = promise.getSemiFuture();
ff::FiberManager::Options opts;
ff::FiberManager manager(std::make_unique<ff::EventBaseLoopController>(), opts);
folly::EventBase evb;
dynamic_cast<ff::EventBaseLoopController&>(manager.loopController()).attachEventBase(evb);
manager.addTask([&]() {
for (auto i = 0; i < 10; ++i) {
++counter;
std::cout << counter << std::endl;
}
});
manager.addTask([&, promise{std::move(promise)}]() mutable {
folly::fibers::Baton sleepBaton;
sleepBaton.try_wait_for(1s);
promise.setValue(42);
});
manager.addTask([&, future{std::move(future)}]() mutable {
auto res = std::move(future).get();
EXPECT_EQ(res, 42);
std::cout << res << std::endl;
});
manager.addTask([&]() {
for (auto i = 0; i < 10; ++i) {
folly::fibers::Baton sleepBaton;
sleepBaton.try_wait_for(100ms);
++counter;
std::cout << counter << std::endl;
}
});
evb.loop();
EXPECT_EQ(counter.load(), 20);
}
int main(int argc, char* argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
И это производит впечатлениечто он работает, как если бы Promise
работал в волокне, что удивительно