folly/futures: fix early release of non-embedded callbacks
authorSven Over <over@fb.com>
Sun, 7 Feb 2016 13:24:01 +0000 (05:24 -0800)
committerfacebook-github-bot-0 <folly-bot@fb.com>
Sun, 7 Feb 2016 14:20:23 +0000 (06:20 -0800)
commitdda657cc57624ebea01a96a54fed2c0c86b398fe
treefe963005178ccfe0d0a59d94b2519eb286e7175f
parentd638ae7a87538e30014a37ba8941f0cec51198a0
folly/futures: fix early release of non-embedded callbacks

Summary:
folly::Future (more precisely folly::detail::Core) can store
callback functors (typically lambdas) up to a certain size
(8*sizeof(void*)) inside the main object. Only bigger functors
are stored in the std::function object in folly::detail::Core,
which will put them on the heap.

The behaviour of folly::Future is slightly different depending
on whether the callback can be embedded in the main object
or not. Small functors will be destructed after the callback
is executed. Functors too big to fit in the lambda space in
the Core object will be deleted when Core is deleted.

Some code assumes that functor objects are deleted as soon
as the callback has been executed. The implementations of
folly::Future::collect and variants do so. If you switch
off this optimisation temporarily (which can be done easily
by setting lambdaBufSize in folly/futures/detail/Core.h to
0), a number of unit tests fail.

Given that the lambda buffer is reasonably large, most
functors can be stored in the Core object. The different
behaviour for very large lambdas may not have been observed.

This diff fixes the inconsitent behaviour.

Firstly, it changes the unit test Future:finish to explicitly
check that the callback functor is deleted after the callback
has been executed. This should be tested, because this
behaviour is assumed in other parts of the futures
implementation (e.g. Future::collect et al.).

Secondly, it adds another unit test Future:finishBigLambda,
similar to Future:finish. The lambda captures much more data
to make sure the lambda won't be stored in the Core object,
but in the std::function object inside Core. The test verifies
that the behaviour is the same, i.e. the callback functor
is destructed after the callback has been executed.

Thirdly, it fixes Core and makes sure that functors of any
size are destructued after the callback has been called. The
new unit test fails without this.

Reviewed By: fugalh

Differential Revision: D2883772

fb-gh-sync-id: 21a410f6592b3e090772a7b55bef6729d8739922
folly/futures/detail/Core.h
folly/futures/test/FutureTest.cpp