Commit 5a81b5df authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Move futures helper types into folly::futures::detail

Summary:
[Folly] Move futures helper types into `folly::futures::detail`.

From `folly::detail`, where it would be easier to collide. Especially for names like `Core`.

Reviewed By: WillerZ

Differential Revision: D5460766

fbshipit-source-id: 3f7bff784bbb89c7c86d2f1824323d71321c7ad6
parent 05a686a7
......@@ -39,17 +39,22 @@ namespace folly {
class Timekeeper;
namespace futures {
namespace detail {
#if FOLLY_FUTURE_USING_FIBER
typedef folly::fibers::Baton FutureBatonType;
#else
typedef folly::Baton<> FutureBatonType;
#endif
}
} // namespace detail
} // namespace futures
namespace detail {
std::shared_ptr<Timekeeper> getTimekeeperSingleton();
} // namespace detail
namespace futures {
namespace detail {
// Guarantees that the stored functor is destructed before the stored promise
// may be fulfilled. Assumes the stored functor to be noexcept-destructible.
template <typename T, typename F>
......@@ -123,11 +128,12 @@ inline auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept(
return CoreCallbackState<T, _t<std::decay<F>>>(
std::move(p), std::forward<F>(f));
}
}
} // namespace detail
} // namespace futures
template <class T>
Future<T> Future<T>::makeEmpty() {
return Future<T>(detail::EmptyConstruct{});
return Future<T>(futures::detail::EmptyConstruct{});
}
template <class T>
......@@ -178,12 +184,12 @@ Future<T>& Future<T>::operator=(Future<T2>&& other) {
template <class T>
template <class T2, typename>
Future<T>::Future(T2&& val)
: core_(new detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
: core_(new futures::detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
template <class T>
template <typename T2>
Future<T>::Future(typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
: core_(new detail::Core<T>(Try<T>(T()))) {}
: core_(new futures::detail::Core<T>(Try<T>(T()))) {}
template <class T>
template <
......@@ -191,7 +197,9 @@ template <
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type>
Future<T>::Future(in_place_t, Args&&... args)
: core_(new detail::Core<T>(in_place, std::forward<Args>(args)...)) {}
: core_(
new futures::detail::Core<T>(in_place, std::forward<Args>(args)...)) {
}
template <class T>
Future<T>::~Future() {
......@@ -238,7 +246,9 @@ Future<T>::unwrap() {
template <class T>
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
Future<T>::thenImplementation(
F&& func,
futures::detail::argResult<isTry, F, Args...>) {
static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B;
......@@ -270,18 +280,18 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
persist beyond the callback, if it gets moved), and so it is an
optimization to just make it shared from the get-go.
Two subtle but important points about this design. detail::Core has no
back pointers to Future or Promise, so if Future or Promise get moved
(and they will be moved in performant code) we don't have to do
Two subtle but important points about this design. futures::detail::Core
has no back pointers to Future or Promise, so if Future or Promise get
moved (and they will be moved in performant code) we don't have to do
anything fancy. And because we store the continuation in the
detail::Core, not in the Future, we can execute the continuation even
after the Future has gone out of scope. This is an intentional design
futures::detail::Core, not in the Future, we can execute the continuation
even after the Future has gone out of scope. This is an intentional design
decision. It is likely we will want to be able to cancel a continuation
in some circumstances, but I think it should be explicit not implicit
in the destruction of the Future used to create it.
*/
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) {
state.setException(std::move(t.exception()));
......@@ -299,7 +309,9 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
template <class T>
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
Future<T>::thenImplementation(
F&& func,
futures::detail::argResult<isTry, F, Args...>) {
static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B;
......@@ -313,7 +325,7 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
f.core_->setExecutorNoLock(getExecutor());
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) {
state.setException(std::move(t.exception()));
......@@ -336,9 +348,9 @@ template <typename T>
template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner>
Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
typedef typename std::remove_cv<
typename std::remove_reference<
typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg;
typedef typename std::remove_cv<typename std::remove_reference<
typename futures::detail::ArgType<Args...>::FirstArg>::type>::type
FirstArg;
return then([instance, func](Try<T>&& t){
return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
});
......@@ -353,13 +365,15 @@ Future<Unit> Future<T>::then() {
template <class T>
template <class F>
typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
!futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
Future<T>::onError(F&& func) {
typedef std::remove_reference_t<typename detail::Extract<F>::FirstArg> Exn;
typedef std::remove_reference_t<
typename futures::detail::Extract<F>::FirstArg>
Exn;
static_assert(
std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
std::is_same<typename futures::detail::Extract<F>::RawReturn, T>::value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
......@@ -367,7 +381,7 @@ Future<T>::onError(F&& func) {
auto f = p.getFuture();
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) {
state.setTry(makeTryWith([&] { return state.invoke(*e); }));
......@@ -383,20 +397,23 @@ Future<T>::onError(F&& func) {
template <class T>
template <class F>
typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
!futures::detail::callableWith<F, exception_wrapper>::value &&
futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
value,
"Return type of onError callback must be T or Future<T>");
typedef std::remove_reference_t<typename detail::Extract<F>::FirstArg> Exn;
typedef std::remove_reference_t<
typename futures::detail::Extract<F>::FirstArg>
Exn;
Promise<T> p;
auto f = p.getFuture();
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) {
auto tf2 = state.tryInvoke(*e);
......@@ -433,18 +450,20 @@ Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
template <class T>
template <class F>
typename std::enable_if<detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
typename std::enable_if<
futures::detail::callableWith<F, exception_wrapper>::value &&
futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
auto f = p.getFuture();
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> t) mutable {
if (t.hasException()) {
auto tf2 = state.tryInvoke(std::move(t.exception()));
......@@ -467,18 +486,19 @@ Future<T>::onError(F&& func) {
template <class T>
template <class F>
typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
auto f = p.getFuture();
setCallback_(
[state = detail::makeCoreCallbackState(
[state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (t.hasException()) {
state.setTry(makeTryWith(
......@@ -574,8 +594,7 @@ void Future<T>::raise(exception_wrapper exception) {
}
template <class T>
Future<T>::Future(detail::EmptyConstruct) noexcept
: core_(nullptr) {}
Future<T>::Future(futures::detail::EmptyConstruct) noexcept : core_(nullptr) {}
// makeFuture
......@@ -638,7 +657,7 @@ makeFuture(E const& e) {
template <class T>
Future<T> makeFuture(Try<T>&& t) {
return Future<T>(new detail::Core<T>(std::move(t)));
return Future<T>(new futures::detail::Core<T>(std::move(t)));
}
// via
......@@ -660,13 +679,13 @@ void mapSetCallback(InputIterator first, InputIterator last, F func) {
// collectAll (variadic)
template <typename... Fs>
typename detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
typename futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectAllVariadicContext>(
ctx, std::forward<Fs>(fs)...);
auto ctx = std::make_shared<futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>>();
futures::detail::collectVariadicHelper<
futures::detail::CollectAllVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture();
}
......@@ -699,6 +718,7 @@ collectAll(InputIterator first, InputIterator last) {
// collect (iterator)
namespace futures {
namespace detail {
template <typename T>
......@@ -737,17 +757,18 @@ struct CollectContext {
std::atomic<bool> threw {false};
};
}
} // namespace detail
} // namespace futures
template <class InputIterator>
Future<typename detail::CollectContext<
typename std::iterator_traits<InputIterator>::value_type::value_type>::Result>
Future<typename futures::detail::CollectContext<typename std::iterator_traits<
InputIterator>::value_type::value_type>::Result>
collect(InputIterator first, InputIterator last) {
typedef
typename std::iterator_traits<InputIterator>::value_type::value_type T;
auto ctx = std::make_shared<detail::CollectContext<T>>(
std::distance(first, last));
auto ctx = std::make_shared<futures::detail::CollectContext<T>>(
std::distance(first, last));
mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
if (t.hasException()) {
if (!ctx->threw.exchange(true)) {
......@@ -763,13 +784,13 @@ collect(InputIterator first, InputIterator last) {
// collect (variadic)
template <typename... Fs>
typename detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
typename futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectVariadicContext>(
ctx, std::forward<Fs>(fs)...);
auto ctx = std::make_shared<futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>>();
futures::detail::collectVariadicHelper<
futures::detail::CollectVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture();
}
......@@ -878,10 +899,10 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) {
}
typedef typename std::iterator_traits<It>::value_type::value_type ItT;
typedef
typename std::conditional<detail::callableWith<F, T&&, Try<ItT>&&>::value,
Try<ItT>,
ItT>::type Arg;
typedef typename std::conditional<
futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
Try<ItT>,
ItT>::type Arg;
typedef isTry<Arg> IsTry;
auto sfunc = std::make_shared<F>(std::move(func));
......@@ -1083,6 +1104,7 @@ Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
});
}
namespace futures {
namespace detail {
template <class T>
......@@ -1130,41 +1152,42 @@ void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
assert(f.isReady());
}
} // detail
} // namespace detail
} // namespace futures
template <class T>
Future<T>& Future<T>::wait() & {
detail::waitImpl(*this);
futures::detail::waitImpl(*this);
return *this;
}
template <class T>
Future<T>&& Future<T>::wait() && {
detail::waitImpl(*this);
futures::detail::waitImpl(*this);
return std::move(*this);
}
template <class T>
Future<T>& Future<T>::wait(Duration dur) & {
detail::waitImpl(*this, dur);
futures::detail::waitImpl(*this, dur);
return *this;
}
template <class T>
Future<T>&& Future<T>::wait(Duration dur) && {
detail::waitImpl(*this, dur);
futures::detail::waitImpl(*this, dur);
return std::move(*this);
}
template <class T>
Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
detail::waitViaImpl(*this, e);
futures::detail::waitViaImpl(*this, e);
return *this;
}
template <class T>
Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
detail::waitViaImpl(*this, e);
futures::detail::waitViaImpl(*this, e);
return std::move(*this);
}
......@@ -1188,20 +1211,23 @@ T Future<T>::getVia(DrivableExecutor* e) {
return std::move(waitVia(e).value());
}
namespace futures {
namespace detail {
template <class T>
struct TryEquals {
static bool equals(const Try<T>& t1, const Try<T>& t2) {
return t1.value() == t2.value();
}
};
}
template <class T>
struct TryEquals {
static bool equals(const Try<T>& t1, const Try<T>& t2) {
return t1.value() == t2.value();
}
};
} // namespace detail
} // namespace futures
template <class T>
Future<bool> Future<T>::willEqual(Future<T>& f) {
return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
return detail::TryEquals<T>::equals(std::get<0>(t), std::get<1>(t));
return futures::detail::TryEquals<T>::equals(
std::get<0>(t), std::get<1>(t));
} else {
return false;
}
......
......@@ -38,6 +38,7 @@ struct isTry : std::false_type {};
template <typename T>
struct isTry<Try<T>> : std::true_type {};
namespace futures {
namespace detail {
template <class> class Core;
......@@ -154,7 +155,8 @@ struct FunctionReferenceToPointer<R (&)(Args...)> {
using type = R (*)(Args...);
};
} // detail
} // namespace detail
} // namespace futures
class Timekeeper;
......
......@@ -210,8 +210,9 @@ class Future {
// replaced with F.
template <
typename F,
typename FF = typename detail::FunctionReferenceToPointer<F>::type,
typename R = detail::callableResult<T, FF>>
typename FF =
typename futures::detail::FunctionReferenceToPointer<F>::type,
typename R = futures::detail::callableResult<T, FF>>
typename R::Return then(F&& func) {
typedef typename R::Arg Arguments;
return thenImplementation<FF, R>(std::forward<FF>(func), Arguments());
......@@ -271,33 +272,33 @@ class Future {
/// });
template <class F>
typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
!futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
onError(F&& func);
/// Overload of onError where the error callback returns a Future<T>
template <class F>
typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
!futures::detail::callableWith<F, exception_wrapper>::value &&
futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns Future<T>
template <class F>
typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
futures::detail::callableWith<F, exception_wrapper>::value &&
futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns T
template <class F>
typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type
onError(F&& func);
/// func is like std::function<void()> and is executed unconditionally, and
......@@ -482,7 +483,7 @@ class Future {
}
protected:
typedef detail::Core<T>* corePtr;
typedef futures::detail::Core<T>* corePtr;
// shared core state object
corePtr core_;
......@@ -490,7 +491,7 @@ class Future {
explicit
Future(corePtr obj) : core_(obj) {}
explicit Future(detail::EmptyConstruct) noexcept;
explicit Future(futures::detail::EmptyConstruct) noexcept;
void detach();
......@@ -529,13 +530,13 @@ class Future {
// e.g. f.then([](Try<T> t){ return t.value(); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
thenImplementation(F&& func, futures::detail::argResult<isTry, F, Args...>);
// Variant: returns a Future
// e.g. f.then([](Try<T> t){ return makeFuture<T>(t); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
thenImplementation(F&& func, futures::detail::argResult<isTry, F, Args...>);
Executor* getExecutor() { return core_->getExecutor(); }
void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
......
......@@ -26,12 +26,12 @@ namespace folly {
template <class T>
Promise<T> Promise<T>::makeEmpty() noexcept {
return Promise<T>(detail::EmptyConstruct{});
return Promise<T>(futures::detail::EmptyConstruct{});
}
template <class T>
Promise<T>::Promise() : retrieved_(false), core_(new detail::Core<T>())
{}
Promise<T>::Promise()
: retrieved_(false), core_(new futures::detail::Core<T>()) {}
template <class T>
Promise<T>::Promise(Promise<T>&& other) noexcept
......@@ -65,7 +65,7 @@ void Promise<T>::throwIfRetrieved() {
}
template <class T>
Promise<T>::Promise(detail::EmptyConstruct) noexcept
Promise<T>::Promise(futures::detail::EmptyConstruct) noexcept
: retrieved_(false), core_(nullptr) {}
template <class T>
......
......@@ -25,11 +25,13 @@ namespace folly {
// forward declaration
template <class T> class Future;
namespace futures {
namespace detail {
struct EmptyConstruct {};
template <typename T, typename F>
class CoreCallbackState;
}
} // namespace detail
} // namespace futures
template <class T>
class Promise {
......@@ -107,7 +109,7 @@ class Promise {
typedef typename Future<T>::corePtr corePtr;
template <class> friend class Future;
template <class, class>
friend class detail::CoreCallbackState;
friend class futures::detail::CoreCallbackState;
// Whether the Future has been retrieved (a one-time operation).
bool retrieved_;
......@@ -115,7 +117,7 @@ class Promise {
// shared core state object
corePtr core_;
explicit Promise(detail::EmptyConstruct) noexcept;
explicit Promise(futures::detail::EmptyConstruct) noexcept;
void throwIfFulfilled();
void throwIfRetrieved();
......
......@@ -34,7 +34,9 @@
#include <folly/io/async/Request.h>
namespace folly { namespace detail {
namespace folly {
namespace futures {
namespace detail {
/*
OnlyCallback
......@@ -450,4 +452,6 @@ void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& ctx,
collectVariadicHelper(ctx, std::forward<TTail>(tail)...);
}
}} // folly::detail
} // namespace detail
} // namespace futures
} // namespace folly
......@@ -21,7 +21,9 @@
#include <folly/MicroSpinLock.h>
namespace folly { namespace detail {
namespace folly {
namespace futures {
namespace detail {
/// Finite State Machine helper base class.
/// Inherit from this.
......@@ -126,5 +128,6 @@ public:
#define FSM_BREAK done = true; break;
#define FSM_END }}}
}} // folly::detail
} // namespace detail
} // namespace futures
} // namespace folly
......@@ -26,6 +26,7 @@
namespace folly {
namespace futures {
namespace detail {
template <typename... Ts>
struct CollectAllVariadicContext {
......@@ -65,7 +66,8 @@ struct CollectVariadicContext {
std::atomic<bool> threw{false};
typedef Future<std::tuple<Ts...>> type;
};
}
} // namespace detail
} // namespace futures
/// This namespace is for utility functions that would usually be static
/// members of Future, except they don't make sense there because they don't
......@@ -228,17 +230,16 @@ auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
/// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
/// The Futures are moved in, so your copies are invalid.
template <typename... Fs>
typename detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
typename futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs);
/// Like collectAll, but will short circuit on the first exception. Thus, the
/// type of the returned Future is std::vector<T> instead of
/// std::vector<Try<T>>
template <class InputIterator>
Future<typename detail::CollectContext<
typename std::iterator_traits<InputIterator>::value_type::value_type
>::result_type>
Future<typename futures::detail::CollectContext<typename std::iterator_traits<
InputIterator>::value_type::value_type>::result_type>
collect(InputIterator first, InputIterator last);
/// Sugar for the most common case
......@@ -251,8 +252,8 @@ auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
/// type of the returned Future is std::tuple<T1, T2, ...> instead of
/// std::tuple<Try<T1>, Try<T2>, ...>
template <typename... Fs>
typename detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
typename futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs);
/** The result is a pair of the index of the first Future to complete and
......@@ -317,16 +318,19 @@ auto collectN(Collection&& c, size_t n)
func must return a Future for each value in input
*/
template <class Collection, class F,
class ItT = typename std::iterator_traits<
typename Collection::iterator>::value_type,
class Result = typename detail::resultOf<F, ItT&&>::value_type>
std::vector<Future<Result>>
window(Collection input, F func, size_t n);
template <
class Collection,
class F,
class ItT = typename std::iterator_traits<
typename Collection::iterator>::value_type,
class Result = typename futures::detail::resultOf<F, ItT&&>::value_type>
std::vector<Future<Result>> window(Collection input, F func, size_t n);
template <typename F, typename T, typename ItT>
using MaybeTryArg = typename std::conditional<
detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
Try<ItT>,
ItT>::type;
template<typename F, typename T, typename Arg>
using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
......
......@@ -26,7 +26,7 @@ TEST(Core, size) {
typename std::aligned_storage<lambdaBufSize>::type lambdaBuf_;
folly::Optional<Try<Unit>> result_;
std::function<void(Try<Unit>&&)> callback_;
detail::FSM<detail::State> fsm_;
futures::detail::FSM<futures::detail::State> fsm_;
std::atomic<unsigned char> attached_;
std::atomic<bool> active_;
std::atomic<bool> interruptHandlerSet_;
......@@ -40,5 +40,5 @@ TEST(Core, size) {
};
// If this number goes down, it's fine!
// If it goes up, please seek professional advice ;-)
EXPECT_GE(sizeof(Gold), sizeof(detail::Core<Unit>));
EXPECT_GE(sizeof(Gold), sizeof(futures::detail::Core<Unit>));
}
......@@ -17,7 +17,7 @@
#include <folly/futures/detail/FSM.h>
#include <folly/portability/GTest.h>
using namespace folly::detail;
using namespace folly::futures::detail;
enum class State { A, B };
......
......@@ -648,7 +648,7 @@ TEST(Future, finishBigLambda) {
// bulk_data, to be captured in the lambda passed to Future::then.
// This is meant to force that the lambda can't be stored inside
// the Future object.
std::array<char, sizeof(detail::Core<int>)> bulk_data = {{0}};
std::array<char, sizeof(futures::detail::Core<int>)> bulk_data = {{0}};
// suppress gcc warning about bulk_data not being used
EXPECT_EQ(bulk_data[0], 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment