mirror of https://gitee.com/bigwinds/arangodb
remove backports
This commit is contained in:
parent
36bde0dfad
commit
c6aef7194b
|
@ -32,7 +32,6 @@
|
|||
#include "Futures/Promise.h"
|
||||
#include "Futures/SharedState.h"
|
||||
#include "Futures/Unit.h"
|
||||
#include "Futures/backports.h"
|
||||
|
||||
namespace arangodb {
|
||||
namespace futures {
|
||||
|
@ -102,7 +101,7 @@ struct valueCallableResult {
|
|||
template <class F, typename R = typename std::result_of<F()>::type>
|
||||
typename std::enable_if<!std::is_same<R, void>::value, Try<R>>::type makeTryWith(F&& func) noexcept {
|
||||
try {
|
||||
return Try<R>(in_place, func());
|
||||
return Try<R>(std::in_place, func());
|
||||
} catch (...) {
|
||||
return Try<R>(std::current_exception());
|
||||
}
|
||||
|
@ -140,10 +139,10 @@ void waitImpl(Future<T>& f) {
|
|||
if (f.isReady()) {
|
||||
return; // short-circuit
|
||||
}
|
||||
|
||||
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
|
||||
|
||||
Promise<T> p;
|
||||
Future<T> ret = p.getFuture();
|
||||
f.thenFinal([p(std::move(p)), &cv, &m](Try<T>&& t) mutable {
|
||||
|
@ -162,14 +161,14 @@ void waitImpl(Future<T>& f, std::chrono::time_point<Clock, Duration> const& tp)
|
|||
if (f.isReady()) {
|
||||
return; // short-circuit
|
||||
}
|
||||
|
||||
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
|
||||
|
||||
Promise<T> p;
|
||||
Future<T> ret = p.getFuture();
|
||||
f.thenFinal([p(std::move(p)), &cv, &m](Try<T>&& t) mutable {
|
||||
std::lock_guard<std::mutex> guard(m);
|
||||
std::lock_guard<std::mutex> guard(m);
|
||||
p.setTry(std::move(t));
|
||||
cv.notify_one();
|
||||
});
|
||||
|
@ -193,7 +192,7 @@ class Future {
|
|||
public:
|
||||
/// @brief value type of the future
|
||||
typedef T value_type;
|
||||
|
||||
|
||||
/// @brief Constructs a Future with no shared state.
|
||||
static Future<T> makeEmpty() { return Future<T>(detail::EmptyConstructor{}); }
|
||||
|
||||
|
@ -211,8 +210,8 @@ class Future {
|
|||
|
||||
// Construct a Future from a `T` constructed from `args`
|
||||
template <class... Args, typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::type = 0>
|
||||
explicit Future(in_place_t, Args&&... args)
|
||||
: _state(detail::SharedState<T>::make(in_place, std::forward<Args>(args)...)) {}
|
||||
explicit Future(std::in_place_t, Args&&... args)
|
||||
: _state(detail::SharedState<T>::make(std::in_place, std::forward<Args>(args)...)) {}
|
||||
|
||||
Future(Future const& o) = delete;
|
||||
Future(Future<T>&& o) noexcept : _state(std::move(o._state)) {
|
||||
|
@ -354,7 +353,7 @@ class Future {
|
|||
pr.setException(std::move(t).exception());
|
||||
} else {
|
||||
pr.setTry(detail::makeTryWith([&fn, &t] {
|
||||
return futures::invoke(std::forward<DF>(fn), std::move(t).get());
|
||||
return std::invoke(std::forward<DF>(fn), std::move(t).get());
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -370,7 +369,7 @@ class Future {
|
|||
using DF = detail::decay_t<F>;
|
||||
|
||||
static_assert(!isFuture<B>::value, "");
|
||||
static_assert(is_invocable_r<Future<B>, F, T>::value,
|
||||
static_assert(std::is_invocable_r<Future<B>, F, T>::value,
|
||||
"Function must be invocable with T");
|
||||
|
||||
Promise<B> promise;
|
||||
|
@ -381,7 +380,7 @@ class Future {
|
|||
pr.setException(std::move(t).exception());
|
||||
} else {
|
||||
try {
|
||||
auto f = futures::invoke(std::forward<DF>(fn), std::move(t).get());
|
||||
auto f = std::invoke(std::forward<DF>(fn), std::move(t).get());
|
||||
std::move(f).then([pr = std::move(pr)](Try<B>&& t) mutable {
|
||||
pr.setTry(std::move(t));
|
||||
});
|
||||
|
@ -409,7 +408,7 @@ class Future {
|
|||
getState().setCallback([fn = std::forward<DF>(func),
|
||||
pr = std::move(promise)](Try<T>&& t) mutable {
|
||||
pr.setTry(detail::makeTryWith([&fn, &t] {
|
||||
return futures::invoke(std::forward<DF>(fn), std::move(t));
|
||||
return std::invoke(std::forward<DF>(fn), std::move(t));
|
||||
}));
|
||||
});
|
||||
return future;
|
||||
|
@ -428,7 +427,7 @@ class Future {
|
|||
getState().setCallback([fn = std::forward<F>(func),
|
||||
pr = std::move(promise)](Try<T>&& t) mutable {
|
||||
try {
|
||||
auto f = futures::invoke(std::forward<F>(fn), std::move(t));
|
||||
auto f = std::invoke(std::forward<F>(fn), std::move(t));
|
||||
std::move(f).then([pr = std::move(pr)](Try<B>&& t) mutable {
|
||||
pr.setTry(std::move(t));
|
||||
});
|
||||
|
@ -465,7 +464,7 @@ class Future {
|
|||
std::rethrow_exception(std::move(t).exception());
|
||||
} catch (ET& e) {
|
||||
pr.setTry(detail::makeTryWith([&fn, &e]() mutable {
|
||||
return futures::invoke(std::forward<DF>(fn), e);
|
||||
return std::invoke(std::forward<DF>(fn), e);
|
||||
}));
|
||||
} catch (...) {
|
||||
pr.setException(std::current_exception());
|
||||
|
@ -494,7 +493,7 @@ class Future {
|
|||
std::rethrow_exception(std::move(t).exception());
|
||||
} catch (ET& e) {
|
||||
try {
|
||||
auto f = futures::invoke(std::forward<DF>(fn), e);
|
||||
auto f = std::invoke(std::forward<DF>(fn), e);
|
||||
std::move(f).then([pr = std::move(pr)](Try<B>&& t) mutable {
|
||||
pr.setTry(std::move(t));
|
||||
});
|
||||
|
|
|
@ -86,8 +86,8 @@ class SharedState {
|
|||
/// State will be OnlyResult
|
||||
/// Result held will be the `T` constructed from forwarded `args`
|
||||
template <typename... Args>
|
||||
static SharedState<T>* make(in_place_t, Args&&... args) {
|
||||
return new SharedState<T>(in_place, std::forward<Args>(args)...);
|
||||
static SharedState<T>* make(std::in_place_t, Args&&... args) {
|
||||
return new SharedState<T>(std::in_place, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// not copyable
|
||||
|
@ -233,9 +233,9 @@ class SharedState {
|
|||
|
||||
/// use to construct a ready future
|
||||
template <typename... Args>
|
||||
explicit SharedState(in_place_t,
|
||||
explicit SharedState(std::in_place_t,
|
||||
Args&&... args) noexcept(std::is_nothrow_constructible<T, Args&&...>::value)
|
||||
: _result(in_place, std::forward<Args>(args)...),
|
||||
: _result(std::in_place, std::forward<Args>(args)...),
|
||||
_state(State::OnlyResult),
|
||||
_attached(1) {}
|
||||
|
||||
|
@ -258,7 +258,7 @@ class SharedState {
|
|||
void doCallback() {
|
||||
TRI_ASSERT(_state == State::Done);
|
||||
TRI_ASSERT(_callback);
|
||||
|
||||
|
||||
_attached.fetch_add(1);
|
||||
// SharedStateScope makes this exception safe
|
||||
SharedStateScope scope(this); // will call detachOne()
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "Basics/Common.h"
|
||||
#include "Basics/debugging.h"
|
||||
#include "Basics/system-compiler.h"
|
||||
#include "Futures/backports.h"
|
||||
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
|
@ -63,7 +62,7 @@ class Try {
|
|||
: _value(std::move(v)), _content(Content::Value) {}
|
||||
|
||||
template <typename... Args>
|
||||
explicit Try(in_place_t,
|
||||
explicit Try(std::in_place_t,
|
||||
Args&&... args) noexcept(std::is_nothrow_constructible<T, Args&&...>::value)
|
||||
: _value(static_cast<Args&&>(args)...), _content(Content::Value) {}
|
||||
|
||||
|
@ -395,7 +394,7 @@ class Try<void> {
|
|||
template <class F, typename R = typename std::result_of<F()>::type>
|
||||
typename std::enable_if<!std::is_same<R, void>::value, Try<R>>::type makeTryWith(F&& func) noexcept {
|
||||
try {
|
||||
return Try<R>(in_place, func());
|
||||
return Try<R>(std::in_place, func());
|
||||
} catch (...) {
|
||||
return Try<R>(std::current_exception());
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2018 ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Simon Grätzer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_FUTURES_BACKPORTS_H
|
||||
#define ARANGOD_FUTURES_BACKPORTS_H 1
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace arangodb {
|
||||
namespace futures {
|
||||
|
||||
/// Backports from C++17 of:
|
||||
/// std::in_place_t
|
||||
/// std::in_place
|
||||
/// std::is_invocable
|
||||
/// std::is_invocable_r
|
||||
/// std::invoke
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
struct in_place_tag {};
|
||||
using in_place_t = in_place_tag (&)(in_place_tag);
|
||||
inline in_place_tag in_place(in_place_tag = {}) { return {}; }
|
||||
|
||||
template <typename F, typename... Args>
|
||||
struct is_invocable
|
||||
: std::is_constructible<std::function<void(Args...)>,
|
||||
std::reference_wrapper<typename std::remove_reference<F>::type>> {
|
||||
};
|
||||
|
||||
template <typename R, typename F, typename... Args>
|
||||
struct is_invocable_r
|
||||
: std::is_constructible<std::function<R(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>> {
|
||||
};
|
||||
|
||||
// mimic: std::invoke, C++17
|
||||
template <typename F, typename... Args>
|
||||
constexpr auto invoke(F&& f, Args&&... args) noexcept(
|
||||
noexcept(static_cast<F&&>(f)(static_cast<Args&&>(args)...)))
|
||||
-> decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...)) {
|
||||
return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
|
||||
}
|
||||
template <typename M, typename C, typename... Args>
|
||||
constexpr auto invoke(M(C::*d), Args&&... args)
|
||||
-> decltype(std::mem_fn(d)(static_cast<Args&&>(args)...)) {
|
||||
return std::mem_fn(d)(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
#else
|
||||
using std::invoke;
|
||||
using in_place_t = std::in_place_t;
|
||||
inline constexpr in_place_t in_place{};
|
||||
|
||||
template <class R, class FN, class... ArgTypes>
|
||||
using is_invocable_r = std::is_invocable_r<R, FN, ArgTypes...>;
|
||||
|
||||
template <class FN, class... ArgTypes>
|
||||
using is_invocable = std::is_invocable<FN, ArgTypes...>;
|
||||
#endif
|
||||
|
||||
} // namespace futures
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -45,27 +45,27 @@ namespace {
|
|||
EXPECT_FALSE(invalid.valid());
|
||||
return invalid;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::decay<T>::type copy(T&& value) noexcept(noexcept(typename std::decay<T>::type(std::forward<T>(value)))) {
|
||||
return std::forward<T>(value);
|
||||
}
|
||||
|
||||
|
||||
int onThenHelperAddOne(int i) {
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
|
||||
int onThenHelperAddFive(int i) {
|
||||
return i + 5;
|
||||
}
|
||||
|
||||
|
||||
Future<int> onThenHelperAddFutureFive(int i) {
|
||||
return makeFuture(i + 5);
|
||||
}
|
||||
|
||||
|
||||
typedef std::domain_error eggs_t;
|
||||
static eggs_t eggs("eggs");
|
||||
|
||||
|
||||
Future<int> onErrorHelperEggs(const eggs_t&) {
|
||||
return makeFuture(10);
|
||||
}
|
||||
|
@ -84,11 +84,11 @@ TEST(FutureTest, basic) {
|
|||
auto f = Future<int>::makeEmpty();
|
||||
EXPECT_ANY_THROW(f.isReady());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, default_ctor) {
|
||||
Future<Unit> abc{};
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, requires_only_move_ctor) {
|
||||
struct MoveCtorOnly {
|
||||
explicit MoveCtorOnly(int id) : id_(id) {}
|
||||
|
@ -98,7 +98,7 @@ TEST(FutureTest, requires_only_move_ctor) {
|
|||
void operator=(MoveCtorOnly&&) = delete;
|
||||
int id_;
|
||||
};
|
||||
|
||||
|
||||
{
|
||||
auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
|
||||
ASSERT_TRUE(f.valid());
|
||||
|
@ -128,11 +128,11 @@ TEST(FutureTest, requires_only_move_ctor) {
|
|||
ASSERT_TRUE(v.id_ == 42);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, ctor_post_condition) {
|
||||
auto const except = std::logic_error("foo");
|
||||
auto const ewrap = std::make_exception_ptr(std::logic_error("foo"));
|
||||
|
||||
|
||||
#define DOIT(CREATION_EXPR) \
|
||||
do { \
|
||||
auto f1 = (CREATION_EXPR); \
|
||||
|
@ -141,7 +141,7 @@ auto f2 = std::move(f1); \
|
|||
ASSERT_FALSE(f1.valid()); \
|
||||
ASSERT_TRUE(f2.valid()); \
|
||||
} while (false)
|
||||
|
||||
|
||||
DOIT(makeValid());
|
||||
DOIT(Future<int>(42));
|
||||
DOIT(Future<int>{42});
|
||||
|
@ -160,7 +160,7 @@ ASSERT_TRUE(f2.valid()); \
|
|||
DOIT(makeFuture<int>(Try<int>(ewrap)));
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, ctor_post_condition_invalid) {
|
||||
#define DOIT(CREATION_EXPR) \
|
||||
do { \
|
||||
|
@ -170,17 +170,17 @@ auto f2 = std::move(f1); \
|
|||
ASSERT_FALSE(f1.valid()); \
|
||||
ASSERT_FALSE(f2.valid()); \
|
||||
} while (false)
|
||||
|
||||
|
||||
DOIT(makeInvalid());
|
||||
DOIT(Future<int>::makeEmpty());
|
||||
|
||||
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, lacksPreconditionValid) {
|
||||
// Ops that don't throw FutureInvalid if !valid() --
|
||||
// without precondition: valid()
|
||||
|
||||
|
||||
#define DOIT(STMT) \
|
||||
do { \
|
||||
auto f = makeValid(); \
|
||||
|
@ -188,15 +188,15 @@ auto f = makeValid(); \
|
|||
::copy(std::move(f)); \
|
||||
STMT; \
|
||||
} while (false)
|
||||
|
||||
|
||||
// .valid() itself
|
||||
DOIT(f.valid());
|
||||
|
||||
|
||||
// move-ctor - move-copy to local, copy(), pass-by-move-value
|
||||
DOIT(auto other = std::move(f));
|
||||
DOIT(copy(std::move(f)));
|
||||
DOIT(([](auto) {})(std::move(f)));
|
||||
|
||||
|
||||
// move-assignment into either {valid | invalid}
|
||||
DOIT({
|
||||
auto other = makeValid();
|
||||
|
@ -206,14 +206,14 @@ STMT; \
|
|||
auto other = makeInvalid();
|
||||
other = std::move(f);
|
||||
});
|
||||
|
||||
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, hasPreconditionValid) {
|
||||
// Ops that require validity; precondition: valid();
|
||||
// throw FutureInvalid if !valid()
|
||||
|
||||
|
||||
#define DOIT(STMT) \
|
||||
do { \
|
||||
auto f = makeValid(); \
|
||||
|
@ -221,7 +221,7 @@ STMT; \
|
|||
::copy(std::move(f)); \
|
||||
EXPECT_ANY_THROW(STMT); \
|
||||
} while (false)
|
||||
|
||||
|
||||
DOIT(f.isReady());
|
||||
DOIT(f.result());
|
||||
DOIT(std::move(f).get());
|
||||
|
@ -233,22 +233,22 @@ EXPECT_ANY_THROW(STMT); \
|
|||
//DOIT(std::move(f).then());
|
||||
DOIT(std::move(f).thenValue([](int&&) noexcept -> void {}));
|
||||
DOIT(std::move(f).thenValue([](auto&&) noexcept -> void {}));
|
||||
|
||||
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, hasPostconditionValid) {
|
||||
// Ops that preserve validity -- postcondition: valid()
|
||||
|
||||
|
||||
#define DOIT(STMT) \
|
||||
do { \
|
||||
auto f = makeValid(); \
|
||||
EXPECT_NO_THROW(STMT); \
|
||||
ASSERT_TRUE(f.valid()); \
|
||||
} while (false)
|
||||
|
||||
|
||||
auto const swallow = [](auto) {};
|
||||
|
||||
|
||||
DOIT(swallow(f.valid())); // f.valid() itself preserves validity
|
||||
DOIT(swallow(f.isReady()));
|
||||
DOIT(swallow(f.hasValue()));
|
||||
|
@ -261,24 +261,24 @@ ASSERT_TRUE(f.valid()); \
|
|||
DOIT(swallow(f.getTry()));
|
||||
DOIT(f.wait());
|
||||
//DOIT(std::move(f.wait()));
|
||||
|
||||
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, lacksPostconditionValid) {
|
||||
// Ops that consume *this -- postcondition: !valid()
|
||||
|
||||
|
||||
#define DOIT(CTOR, STMT) \
|
||||
do { \
|
||||
auto f = (CTOR); \
|
||||
STMT; \
|
||||
ASSERT_FALSE(f.valid()); \
|
||||
} while (false)
|
||||
|
||||
|
||||
// move-ctor of {valid|invalid}
|
||||
DOIT(makeValid(), { auto other{std::move(f)}; });
|
||||
DOIT(makeInvalid(), { auto other{std::move(f)}; });
|
||||
|
||||
|
||||
// move-assignment of {valid|invalid} into {valid|invalid}
|
||||
DOIT(makeValid(), {
|
||||
auto other = makeValid();
|
||||
|
@ -296,7 +296,7 @@ ASSERT_FALSE(f.valid()); \
|
|||
auto other = makeInvalid();
|
||||
other = std::move(f);
|
||||
});
|
||||
|
||||
|
||||
// pass-by-value of {valid|invalid}
|
||||
DOIT(makeValid(), {
|
||||
auto const byval = [](auto) {};
|
||||
|
@ -306,7 +306,7 @@ ASSERT_FALSE(f.valid()); \
|
|||
auto const byval = [](auto) {};
|
||||
byval(std::move(f));
|
||||
});
|
||||
|
||||
|
||||
// other consuming ops
|
||||
auto const swallow = [](auto) {};
|
||||
//DOIT(makeValid(), swallow(std::move(f).wait()));
|
||||
|
@ -314,10 +314,10 @@ ASSERT_FALSE(f.valid()); \
|
|||
DOIT(makeValid(), swallow(std::move(f).get()));
|
||||
DOIT(makeValid(), swallow(std::move(f).get(std::chrono::milliseconds(10))));
|
||||
//DOIT(makeValid(), swallow(std::move(f).semi()));
|
||||
|
||||
|
||||
#undef DOIT
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, thenError) {
|
||||
bool theFlag = false;
|
||||
auto flag = [&] { theFlag = true; };
|
||||
|
@ -327,13 +327,13 @@ f.wait(); \
|
|||
ASSERT_TRUE(theFlag); \
|
||||
theFlag = false; \
|
||||
} while (0);
|
||||
|
||||
|
||||
#define EXPECT_NO_FLAG() \
|
||||
do { \
|
||||
ASSERT_FALSE(theFlag); \
|
||||
theFlag = false; \
|
||||
} while (0);
|
||||
|
||||
|
||||
// By reference
|
||||
{
|
||||
auto f = makeFuture()
|
||||
|
@ -342,7 +342,7 @@ theFlag = false; \
|
|||
EXPECT_FLAG();
|
||||
EXPECT_NO_THROW(f.get());
|
||||
}
|
||||
|
||||
|
||||
// By auto reference
|
||||
{
|
||||
auto f = makeFuture()
|
||||
|
@ -534,7 +534,7 @@ theFlag = false; \
|
|||
.thenError<eggs_t&>([&](eggs_t& e) -> Future<int> { throw e; });
|
||||
EXPECT_THROW(f.get(), eggs_t);
|
||||
}
|
||||
|
||||
|
||||
// // exception_wrapper, return Future<T>
|
||||
// {
|
||||
// auto f = makeFuture()
|
||||
|
@ -597,7 +597,7 @@ theFlag = false; \
|
|||
#undef EXPECT_FLAG
|
||||
#undef EXPECT_NO_FLAG
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, special) {
|
||||
ASSERT_FALSE(std::is_copy_constructible<Future<int>>::value);
|
||||
ASSERT_FALSE(std::is_copy_assignable<Future<int>>::value);
|
||||
|
@ -628,23 +628,23 @@ TEST(FutureTest, then) {
|
|||
std::string value = f.get();
|
||||
ASSERT_TRUE(value == "1;2;3;4;5;6;7;8;9;10;11");
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, then_static_functions) {
|
||||
auto f = makeFuture<int>(10).thenValue(onThenHelperAddFive);
|
||||
ASSERT_TRUE(f.get() == 15);
|
||||
|
||||
|
||||
auto f2 = makeFuture<int>(15).thenValue(onThenHelperAddFutureFive);
|
||||
ASSERT_TRUE(f2.get() == 20);
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, get) {
|
||||
auto f = makeFuture(std::make_unique<int>(42));
|
||||
auto up = std::move(f).get();
|
||||
ASSERT_TRUE(42 == *up);
|
||||
|
||||
|
||||
EXPECT_THROW(makeFuture<int>(eggs).get(), eggs_t);
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, isReady) {
|
||||
Promise<int> p;
|
||||
auto f = p.getFuture();
|
||||
|
@ -652,76 +652,76 @@ TEST(FutureTest, isReady) {
|
|||
p.setValue(42);
|
||||
ASSERT_TRUE(f.isReady());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, futureNotReady) {
|
||||
Promise<int> p;
|
||||
Future<int> f = p.getFuture();
|
||||
EXPECT_THROW(f.result().get(), FutureException);
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, makeFuture) {
|
||||
ASSERT_TRUE(makeFuture<int>(eggs).getTry().hasException());
|
||||
ASSERT_FALSE(makeFuture(42).getTry().hasException());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, hasValue) {
|
||||
ASSERT_TRUE(makeFuture(42).getTry().hasValue());
|
||||
ASSERT_FALSE(makeFuture<int>(eggs).getTry().hasValue());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, makeFuture2) {
|
||||
//EXPECT_TYPE(makeFuture(42), Future<int>);
|
||||
ASSERT_TRUE(42 == makeFuture(42).get());
|
||||
|
||||
|
||||
//EXPECT_TYPE(makeFuture<float>(42), Future<float>);
|
||||
ASSERT_TRUE(42 == makeFuture<float>(42).get());
|
||||
|
||||
|
||||
auto fun = [] { return 42; };
|
||||
//EXPECT_TYPE(makeFutureWith(fun), Future<int>);
|
||||
ASSERT_TRUE(42 == makeFutureWith(fun).get());
|
||||
|
||||
|
||||
auto funf = [] { return makeFuture<int>(43); };
|
||||
//EXPECT_TYPE(makeFutureWith(funf), Future<int>);
|
||||
ASSERT_TRUE(43 == makeFutureWith(funf).get());
|
||||
|
||||
|
||||
auto failfun = []() -> int { throw eggs; };
|
||||
//EXPECT_TYPE(makeFutureWith(failfun), Future<int>);
|
||||
EXPECT_NO_THROW(makeFutureWith(failfun));
|
||||
EXPECT_THROW(makeFutureWith(failfun).get(), eggs_t);
|
||||
|
||||
|
||||
auto failfunf = []() -> Future<int> { throw eggs; };
|
||||
//EXPECT_TYPE(makeFutureWith(failfunf), Future<int>);
|
||||
EXPECT_NO_THROW(makeFutureWith(failfunf));
|
||||
EXPECT_THROW(makeFutureWith(failfunf).get(), eggs_t);
|
||||
|
||||
|
||||
//EXPECT_TYPE(makeFuture(), Future<Unit>);
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, finish) {
|
||||
auto x = std::make_shared<int>(0);
|
||||
|
||||
|
||||
Promise<int> p;
|
||||
auto f = p.getFuture().then([x](Try<int>&& t) { *x = t.get(); });
|
||||
|
||||
|
||||
// The callback hasn't executed
|
||||
ASSERT_TRUE(0 == *x);
|
||||
|
||||
|
||||
// The callback has a reference to x
|
||||
ASSERT_TRUE(2 == x.use_count());
|
||||
|
||||
|
||||
p.setValue(42);
|
||||
f.wait();
|
||||
|
||||
|
||||
// the callback has executed
|
||||
ASSERT_EQ(42, *x);
|
||||
|
||||
|
||||
std::this_thread::yield();
|
||||
|
||||
|
||||
// the callback has been destructed
|
||||
// and has released its reference to x
|
||||
ASSERT_EQ(1, x.use_count());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, detachRace) {
|
||||
// This test is designed to detect a race that was in Core::detachOne()
|
||||
// where detached_ was incremented and then tested, and that
|
||||
|
@ -737,7 +737,7 @@ TEST(FutureTest, detachRace) {
|
|||
//folly::Baton<> baton;
|
||||
std::mutex m;
|
||||
std::condition_variable condition;
|
||||
|
||||
|
||||
std::unique_lock<std::mutex> guard(m);
|
||||
std::thread t1([&]{
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
|
@ -788,7 +788,7 @@ TEST(FutureTest, ImplicitConstructor) {
|
|||
}
|
||||
|
||||
TEST(FutureTest, InPlaceConstructor) {
|
||||
auto f = Future<std::pair<int, double>>(in_place, 5, 3.2);
|
||||
auto f = Future<std::pair<int, double>>(std::in_place, 5, 3.2);
|
||||
ASSERT_TRUE(5 == f.get().first);
|
||||
}
|
||||
|
||||
|
@ -843,7 +843,7 @@ TEST(FutureTest, invokeCallbackReturningFutureAsRvalue) {
|
|||
ASSERT_TRUE(202 == makeFuture<int>(200).thenValue(cfoo).get());
|
||||
ASSERT_TRUE(303 == makeFuture<int>(300).thenValue(Foo()).get());
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, basic_example) {
|
||||
Promise<int> p;
|
||||
Future<int> f = p.getFuture();
|
||||
|
@ -851,7 +851,7 @@ TEST(FutureTest, basic_example) {
|
|||
p.setValue(42);
|
||||
ASSERT_TRUE(f2.get() == 43);
|
||||
}
|
||||
|
||||
|
||||
TEST(FutureTest, basic_example_fpointer) {
|
||||
Promise<int> p;
|
||||
Future<int> f = p.getFuture();
|
||||
|
|
|
@ -92,13 +92,13 @@ TEST(FuturesTryTest, Basic) {
|
|||
}
|
||||
|
||||
TEST(FuturesTryTest, in_place) {
|
||||
Try<A> t_a(in_place, 5);
|
||||
Try<A> t_a(std::in_place, 5);
|
||||
|
||||
ASSERT_TRUE(5 == t_a.get().x());
|
||||
}
|
||||
|
||||
TEST(FuturesTryTest, in_place_nested) {
|
||||
Try<Try<A>> t_t_a(in_place, in_place, 5);
|
||||
Try<Try<A>> t_t_a(std::in_place, std::in_place, 5);
|
||||
|
||||
ASSERT_TRUE(5 == t_t_a.get().get().x());
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ TEST(FuturesTryTest, assignment_with_throwing_ctor) {
|
|||
int counter = 0;
|
||||
|
||||
{
|
||||
Try<ThrowingCopyConstructor> t1{in_place, counter};
|
||||
Try<ThrowingCopyConstructor> t2{in_place, counter};
|
||||
Try<ThrowingCopyConstructor> t1{std::in_place, counter};
|
||||
Try<ThrowingCopyConstructor> t2{std::in_place, counter};
|
||||
ASSERT_TRUE(2 == counter);
|
||||
EXPECT_ANY_THROW(t2 = t1);
|
||||
EXPECT_ANY_THROW(t2 = t1);
|
||||
|
@ -135,7 +135,7 @@ TEST(FuturesTryTest, assignment_with_throwing_ctor) {
|
|||
}
|
||||
ASSERT_TRUE(0 == counter);
|
||||
{
|
||||
Try<ThrowingCopyConstructor> t1{in_place, counter};
|
||||
Try<ThrowingCopyConstructor> t1{std::in_place, counter};
|
||||
Try<ThrowingCopyConstructor> t2;
|
||||
ASSERT_TRUE(1 == counter);
|
||||
EXPECT_ANY_THROW(t2 = t1);
|
||||
|
@ -173,12 +173,12 @@ TEST(FuturesTryTest, MoveConstRvalue) {
|
|||
// where for example MutableContainer has a mutable member that is move only
|
||||
// and you want to fetch the value from the Try and move it into a member
|
||||
{
|
||||
const Try<MutableContainer> t{in_place};
|
||||
const Try<MutableContainer> t{std::in_place};
|
||||
auto val = MoveConstructOnly(std::move(t).get().val);
|
||||
static_cast<void>(val);
|
||||
}
|
||||
{
|
||||
const Try<MutableContainer> t{in_place};
|
||||
const Try<MutableContainer> t{std::in_place};
|
||||
auto val = (*(std::move(t))).val;
|
||||
static_cast<void>(val);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue