33 #include <type_traits> 35 using namespace folly;
37 #define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value)) 87 explicit MoveCtorOnly(
int id) : id_(
id) {}
88 MoveCtorOnly(
const MoveCtorOnly&) =
delete;
89 MoveCtorOnly(MoveCtorOnly&&) =
default;
90 void operator=(MoveCtorOnly
const&) =
delete;
91 void operator=(MoveCtorOnly&&) =
delete;
95 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
102 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
109 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
112 auto v =
std::move(
f).get(std::chrono::milliseconds(10));
116 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
119 auto v =
std::move(
f).get(std::chrono::milliseconds(10));
126 auto valid = makeFuture<int>(42);
140 #define DOIT(CREATION_EXPR) \ 142 auto f1 = (CREATION_EXPR); \ 143 EXPECT_TRUE(f1.valid()); \ 144 auto f2 = std::move(f1); \ 145 EXPECT_FALSE(f1.valid()); \ 146 EXPECT_TRUE(f2.valid()); \ 149 auto const except = std::logic_error(
"foo");
161 DOIT(makeFuture<int>(42));
162 DOIT(makeFuture<int>(except));
163 DOIT(makeFuture<int>(ewrap));
174 #define DOIT(CREATION_EXPR) \ 176 auto f1 = (CREATION_EXPR); \ 177 EXPECT_FALSE(f1.valid()); \ 178 auto f2 = std::move(f1); \ 179 EXPECT_FALSE(f1.valid()); \ 180 EXPECT_FALSE(f2.valid()); \ 195 auto f = makeValid(); \ 197 copy(std::move(f)); \ 198 EXPECT_NO_THROW(STMT); \ 211 auto other = makeValid();
215 auto other = makeInvalid();
228 auto f = makeValid(); \ 229 EXPECT_NO_THROW(STMT); \ 230 copy(std::move(f)); \ 231 EXPECT_THROW(STMT, FutureInvalid); \ 240 DOIT(
f.hasException());
254 auto f = makeValid(); \ 255 EXPECT_NO_THROW(STMT); \ 256 EXPECT_TRUE(f.valid()); \ 259 auto const swallow = [](
auto) {};
261 DOIT(swallow(
f.valid()));
262 DOIT(swallow(
f.isReady()));
263 DOIT(swallow(
f.hasValue()));
264 DOIT(swallow(
f.hasException()));
265 DOIT(swallow(
f.value()));
266 DOIT(swallow(
f.getTry()));
267 DOIT(swallow(
f.poll()));
268 DOIT(
f.raise(std::logic_error(
"foo")));
270 DOIT(swallow(
f.getTry()));
280 #define DOIT(CTOR, STMT) \ 283 EXPECT_NO_THROW(STMT); \ 284 EXPECT_FALSE(f.valid()); \ 293 auto other = makeValid();
297 auto other = makeInvalid();
300 DOIT(makeInvalid(), {
301 auto other = makeValid();
304 DOIT(makeInvalid(), {
305 auto other = makeInvalid();
311 auto const byval = [](
auto) {};
314 DOIT(makeInvalid(), {
315 auto const byval = [](
auto) {};
320 auto const swallow = [](
auto) {};
324 DOIT(makeValid(), swallow(
std::move(
f).
get(std::chrono::milliseconds(10))));
334 Future<int> onErrorHelperGeneric(
const std::exception&) {
343 bool theFlag =
false;
344 auto flag = [&] { theFlag =
true; };
345 #define EXPECT_FLAG() \ 347 EXPECT_TRUE(theFlag); \ 351 #define EXPECT_NO_FLAG() \ 353 EXPECT_FALSE(theFlag); \ 360 .thenValue([](
auto&&) {
throw eggs; })
368 .thenValue([](
auto&&) {
throw eggs; })
380 .thenValue([](
auto&&) {
throw eggs; })
388 .thenValue([](
auto&&) {
throw eggs; })
400 .thenValue([](
auto&&) {
throw eggs; })
401 .onError([&](std::exception& ) {
flag(); });
408 .thenValue([](
auto&&) {
throw eggs; })
409 .onError([&](std::exception& ) {
420 .thenValue([](
auto&&) {
throw - 1; })
421 .onError([&](
int ) {
flag(); });
428 .thenValue([](
auto&&) {
throw - 1; })
440 .thenValue([](
auto&&) {
throw eggs; })
448 .thenValue([](
auto&&) {
throw eggs; })
449 .onError([&](
eggs_t& )
mutable {
460 .thenValue([](
auto &&) ->
int {
throw eggs; })
461 .onError(onErrorHelperEggs)
462 .onError(onErrorHelperGeneric);
468 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
469 .onError(onErrorHelperEggs)
470 .onError(onErrorHelperGeneric);
476 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
477 .onError(onErrorHelperEggs);
482 .thenValue([](
auto &&) ->
int {
throw eggs; })
483 .thenError<eggs_t>(onErrorHelperEggs)
484 .thenError<std::exception>(onErrorHelperGeneric);
490 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
491 .thenError<eggs_t>(onErrorHelperEggs)
492 .thenError(onErrorHelperWrapper);
498 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
499 .thenError<eggs_t>(onErrorHelperEggs);
506 .thenValue([](
auto&&) {
return 42; })
517 .thenValue([](
auto&&) {
return 42; })
520 return makeFuture<int>(-1);
529 .thenValue([](
auto&&) {
throw eggs; })
530 .onError([&](std::runtime_error& ) {
flag(); });
537 .thenValue([](
auto&&) {
throw eggs; })
538 .onError([&](std::runtime_error& ) {
549 .thenValue([](
auto &&) ->
int {
throw eggs; })
550 .onError([&](
eggs_t& ) {
return 42; });
557 .thenValue([](
auto &&) ->
int {
throw eggs; })
558 .onError([&](
eggs_t& ) {
return makeFuture<int>(42); });
565 .thenValue([](
auto &&) ->
int {
throw eggs; })
566 .onError([&](
eggs_t& e) ->
int {
throw e; });
572 .thenValue([](
auto &&) ->
int {
throw eggs; })
580 .thenValue([](
auto&&) {
throw eggs; })
592 .thenValue([](
auto &&) ->
int {
throw eggs; })
604 .thenValue([](
auto &&) ->
int {
throw eggs; })
616 .thenValue([](
auto &&) ->
int {
throw eggs; })
628 .thenValue([](
auto&&) {
throw eggs; })
637 #undef EXPECT_NO_FLAG 641 bool theFlag =
false;
642 auto flag = [&] { theFlag =
true; };
643 #define EXPECT_FLAG() \ 645 EXPECT_TRUE(theFlag); \ 649 #define EXPECT_NO_FLAG() \ 651 EXPECT_FALSE(theFlag); \ 658 .thenValue([](
auto&&) {
throw eggs; })
659 .thenError<eggs_t>([&](
const eggs_t& ) {
flag(); });
667 .thenValue([](
auto&&) {
throw eggs; })
668 .thenError<eggs_t>([&](
auto const& ) {
flag(); });
675 .thenValue([](
auto&&) {
throw eggs; })
687 .thenValue([](
auto&&) {
throw eggs; })
695 .thenValue([](
auto&&) {
throw eggs; })
707 .thenValue([](
auto&&) {
throw eggs; })
708 .onError([&](std::exception& ) {
flag(); });
715 .thenValue([](
auto&&) {
throw eggs; })
716 .onError([&](std::exception& ) {
727 .thenValue([](
auto&&) {
throw - 1; })
728 .onError([&](
int ) {
flag(); });
735 .thenValue([](
auto&&) {
throw - 1; })
747 .thenValue([](
auto&&) {
throw eggs; })
755 .thenValue([](
auto&&) {
throw eggs; })
756 .onError([&](
eggs_t& )
mutable {
767 .thenValue([](
auto &&) ->
int {
throw eggs; })
768 .onError(onErrorHelperEggs)
769 .onError(onErrorHelperGeneric);
775 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
776 .onError(onErrorHelperEggs)
777 .onError(onErrorHelperGeneric);
783 .thenValue([](
auto &&) ->
int {
throw std::runtime_error(
"test"); })
784 .onError(onErrorHelperEggs);
791 .thenValue([](
auto&&) {
return 42; })
802 .thenValue([](
auto&&) {
return 42; })
805 return makeFuture<int>(-1);
814 .thenValue([](
auto&&) {
throw eggs; })
815 .onError([&](std::runtime_error& ) {
flag(); });
822 .thenValue([](
auto&&) {
throw eggs; })
823 .onError([&](std::runtime_error& ) {
834 .thenValue([](
auto &&) ->
int {
throw eggs; })
835 .onError([&](
eggs_t& ) {
return 42; });
842 .thenValue([](
auto &&) ->
int {
throw eggs; })
843 .onError([&](
eggs_t& ) {
return makeFuture<int>(42); });
850 .thenValue([](
auto &&) ->
int {
throw eggs; })
851 .onError([&](
eggs_t& e) ->
int {
throw e; });
857 .thenValue([](
auto &&) ->
int {
throw eggs; })
865 .thenValue([](
auto&&) {
throw eggs; })
877 .thenValue([](
auto &&) ->
int {
throw eggs; })
889 .thenValue([](
auto &&) ->
int {
throw eggs; })
901 .thenValue([](
auto &&) ->
int {
throw eggs; })
913 .thenValue([](
auto&&) {
throw eggs; })
922 #undef EXPECT_NO_FLAG 934 makeFuture<std::string>(
"0")
935 .thenValue([](
auto&&) {
return makeFuture<std::string>(
"1"); })
953 EXPECT_EQ(
f.value(),
"1;2;3;4;5;6;7;8;9;10;11");
963 .thenTry([](
auto&&) {
return makeFuture<std::string>(
"1"); })
983 EXPECT_EQ(
f.value(),
"1;2;3;4;5;6;7;8;9;10;11;12");
989 makeFuture<int>(42).then([&](
Try<int>&&
t) {
1023 makeFuture<int>(42).then([&](
int i) {
1030 makeFuture<int>(42).then([](
int i) {
return i; }).then([&](
int i) {
1037 makeFuture().thenValue([&](
auto&&) { flag =
true; });
1041 auto f = makeFuture<int>(
eggs).thenValue([&](
int ) {});
1044 f = makeFuture<Unit>(
eggs).thenValue([&](
auto&&) {});
1051 .then([](
int i) {
return makeFuture<int>(
std::move(i)); })
1060 .thenValue([](
auto&&) {
return makeFuture(); })
1061 .then([&](
Try<Unit>&& ) { flag =
true; });
1067 return t.value() +
";static";
1071 return t +
";value";
1077 return t.value() +
";class";
1080 return t.value() +
";class-static";
1084 auto f = makeFuture<std::string>(
"start")
1091 EXPECT_EQ(
f.value(),
"start;static;class-static;class;value;value");
1108 auto f = makeFuture<std::string>(
"start")
1111 .then(&Worker::doWorkFuture, &w);
1113 EXPECT_EQ(
f.value(),
"start;static;class-static;class");
1118 std::function<int(folly::Unit)> fn = [](
folly::Unit) {
return 42; };
1123 std::function<int(int)> fn = [](
int i) {
return i + 23; };
1128 std::function<int(int)> fn = [](
int i) {
return i + 23; };
1133 std::function<int(Try<int>)> fn = [](
Try<int> t) {
return t.
value() + 2; };
1139 std::function<void(folly::Unit)> fn = [&
flag](
folly::Unit) { flag =
true; };
1148 auto b =
std::bind(l, std::placeholders::_1);
1155 auto b =
std::bind(l, std::placeholders::_1);
1156 auto f = makeFuture<std::string>(
"start").then(
std::move(
b));
1200 auto fun = [] {
return 42; };
1204 auto funf = [] {
return makeFuture<int>(43); };
1208 auto failfun = []() ->
int {
throw eggs; };
1222 auto x = std::make_shared<int>(0);
1225 auto f = p.getFuture().then([
x](
Try<int>&&
t) { *
x =
t.value(); });
1244 auto x = std::make_shared<int>(0);
1249 std::array<char, sizeof(futures::detail::Core<int>)> bulk_data = {{0}};
1288 auto va = ta.value();
1292 return va + tb.value();
1319 makeFuture<Unit>(
eggs).then(
1323 makeFuture<int>(
eggs).then(
1325 makeFuture<int>(42).then(
1337 p.
setWith([]() ->
void {
throw std::logic_error(
"foo"); });
1352 auto p = std::make_unique<Promise<bool>>();
1353 auto f = std::make_unique<Future<bool>>(p->getFuture());
1355 std::thread t1([&] {
1369 auto ptr = std::make_shared<Future<int64_t>>(promise.
getFuture());
1372 EXPECT_EQ(1, ptr.use_count());
1376 EXPECT_EQ(0, ptr.use_count());
1418 class NewThreadExecutor :
public Executor {
1420 ~NewThreadExecutor()
override {
1421 std::for_each(v_.begin(), v_.end(), [](std::thread&
t) {
t.join(); });
1425 throw std::exception();
1429 void addWithPriority(
Func f,
int8_t )
override {
1432 uint8_t getNumPriorities()
const override {
1433 return numPriorities_;
1436 void setHandlesPriorities() {
1439 void setThrowsOnAdd() {
1440 throwsOnAdd_ =
true;
1444 std::vector<std::thread> v_;
1446 bool throwsOnAdd_ =
false;
1450 MyRequestData(
bool value_ =
false) :
value(value_) {}
1452 bool hasCallback()
override {
1460 NewThreadExecutor e;
1464 "key", std::make_unique<MyRequestData>(
true));
1465 auto checker = [](
int lineno) {
1467 auto d =
static_cast<MyRequestData*
>(
1469 EXPECT_TRUE(d && d->value) <<
"on line " << lineno;
1473 makeFuture(1).via(&e).then(checker(__LINE__));
1475 e.setHandlesPriorities();
1476 makeFuture(2).via(&e).then(checker(__LINE__));
1481 p2.
getFuture().via(&e).then(checker(__LINE__));
1495 int operator()(
int x) & {
1498 int operator()(
int x)
const& {
1501 int operator()(
int x) && {
1547 std::weak_ptr<int> target;
1550 auto input = std::make_shared<int>(1);
1551 auto longEnough = std::chrono::milliseconds(1000);
1556 folly::Try<std::shared_ptr<int>>&& callbackInput)
mutable {
1557 target = callbackInput.value();
1568 auto veryShort = std::chrono::milliseconds(1);
1570 promise.
getFuture().within(veryShort).then(
1571 [](
folly::Try<std::shared_ptr<int>>&& callbackInput) {
1573 EXPECT_EQ(0, callbackInput.value().use_count());
1580 std::queue<Func> queue_;
1587 while (!queue_.empty()) {
1596 auto c = makePromiseContract<int>(&e);
1597 c.second =
std::move(
c.second).then([](
int _) {
return _ + 1; });
1599 c.first.setValue(3);
1607 return makeFuture().then(executor, [=] {
return depth == 0; });
1612 return call(depth, executor).thenValue([=](
auto result) {
#define DOIT(CREATION_EXPR)
#define EXPECT_NO_THROW(statement)
#define EXPECT_THROW(statement, expected_exception)
Future< int > recursion(Executor *executor, int depth)
void setContextData(const RequestToken &val, std::unique_ptr< RequestData > data)
#define EXPECT_EQ(val1, val2)
static std::string doWorkStaticValue(std::string &&t)
constexpr detail::Map< Move > move
—— Concurrent Priority Queue Implementation ——
in_place_tag in_place(in_place_tag={})
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
static folly::Future< std::string > doWorkStaticTry(Try< std::string > &&t)
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
static std::shared_ptr< RequestContext > saveContext()
static eggs_t eggs("eggs")
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
#define EXPECT_TRUE(condition)
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
std::pair< Promise< T >, SemiFuture< T > > makePromiseContract()
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
constexpr detail::Unwrap unwrap
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
const internal::AnythingMatcher _
void for_each(T const &range, Function< void(typename T::value_type const &) const > const &func)
#define EXPECT_FALSE(condition)
RequestData * getContextData(const RequestToken &val)
static std::string doWorkStatic(Try< std::string > &&t)
static Future< std::string > doWorkStaticFuture(Try< std::string > &&t)
#define ASSERT_TRUE(condition)
#define EXPECT_TYPE(x, T)
TEST(SequencedExecutor, CPUThreadPoolExecutor)
static RequestContext * get()
Future< typename std::decay< T >::type > makeFuture(T &&t)
Future< bool > call(int depth, Executor *executor)
std::enable_if< isFuture< invoke_result_t< F > >::value, invoke_result_t< F > >::type makeFutureWith(F &&func)
static Future< T > makeEmpty()