folly/futures: use folly::Function to store callback
Summary:This diff makes it possible to pass callables (such as lambdas) to
folly::Future::then that are not copy-constructible. As a consequence, move-only
types (such as folly::Promise or std::unique_ptr) can now be captured in lambdas
passed to folly::Future::then.
Using C++14 notation, the following is now possible:
Future<Unit>().then([promise = std::move(promise)]() mutable {
promise.setValue(123);
});
See folly/futures/test/NonCopyableLambdaTest.cpp for more examples.
folly::Future uses std::function to store callback functions. (More precisely,
the callback function is stored in a std::function in folly::detail::Core.)
std::function is a copy-constructible type and it requires that the callable
that it stores is copy constructible as well.
This diff changes the implementation of folly::detail::Core to use
folly::Function instead of std::function. It also simplifies the code in
folly::detail::Core a little bit: Core had a reserved space of size
8*sizeof(void*) to store callbacks in-place. Only larger callbacks (capturing
more data) would be stored in the std::function, which puts those on the heap.
folly::Function has a template parameter to set the size of the in-place
callable storage. In Core, it is set to 8*sizeof(void*), so all callbacks that
used to be stored in-place inside Core, are now stored in-place inside
folly::Function. This even reduces the size of a Core object: the
folly::Function object occupies 80 bytes, which is 16 bytes less than what was
used before for a std::function (32 bytes) and the callback storage (64
bytes). The resulting size of a Core<Unit> goes down from 192 to 176 bytes (on
x86_64).
Reviewed By: fugalh
Differential Revision:
D2884868
fb-gh-sync-id:
35548890c392f80e6c680676b0f98e711bc03ca3
fbshipit-source-id:
35548890c392f80e6c680676b0f98e711bc03ca3