Folly的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
在光纤中工作一样令人惊讶