Commit a4ef724b authored by Dave Watson's avatar Dave Watson Committed by Facebook Github Bot

Initialize call_ and exec_ in move constructor

Summary: It's only two stores, but for move that ends up being a large percentage of the work it has to do.  Add initializers in the move constructor, so that we don't both default-initialize and then swap() inline.

Reviewed By: yfeldblum

Differential Revision: D8678422

fbshipit-source-id: 71b574145182ad3a4a3e9d0d824d83abe65fb6fa
parent 5c02ae45
......@@ -571,12 +571,11 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
Function(Function<Signature>&& that, CoerceTag)
: Function(static_cast<Function<Signature>&&>(that), HeapTag{}) {}
Function(
Function<typename Traits::OtherSignature>&& that,
CoerceTag) noexcept {
that.exec(Op::MOVE, &that.data_, &data_);
std::swap(call_, that.call_);
std::swap(exec_, that.exec_);
Function(Function<typename Traits::OtherSignature>&& that, CoerceTag) noexcept
: call_(that.call_), exec_(that.exec_) {
that.call_ = &Traits::uninitCall;
that.exec_ = nullptr;
exec(Op::MOVE, &that.data_, &data_);
}
public:
......@@ -599,10 +598,11 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
/**
* Move constructor
*/
Function(Function&& that) noexcept {
that.exec(Op::MOVE, &that.data_, &data_);
std::swap(call_, that.call_);
std::swap(exec_, that.exec_);
Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
// that must be uninitialized before exec() call in the case of self move
that.call_ = &Traits::uninitCall;
that.exec_ = nullptr;
exec(Op::MOVE, &that.data_, &data_);
}
/**
......
......@@ -1096,6 +1096,34 @@ TEST(Function, SelfMove) {
EXPECT_EQ(43, f());
}
TEST(Function, SelfMove2) {
int alive{0};
struct arg {
int* ptr_;
explicit arg(int* ptr) noexcept : ptr_(ptr) {
++*ptr_;
}
arg(arg&& o) noexcept : ptr_(o.ptr_) {
++*ptr_;
}
arg& operator=(arg&&) = delete;
~arg() {
--*ptr_;
}
};
EXPECT_EQ(0, alive);
Function<int()> f = [myarg = arg{&alive}] { return 42; };
EXPECT_EQ(1, alive);
Function<int()>& g = f;
f = std::move(g);
EXPECT_FALSE(bool(f)) << "self-assign is self-destruct";
EXPECT_EQ(0, alive) << "self-asign is self-destruct";
f = [] { return 43; };
EXPECT_EQ(0, alive) << "sanity check against double-destruction";
EXPECT_TRUE(bool(f));
EXPECT_EQ(43, f());
}
TEST(Function, DeducableArguments) {
deduceArgs(Function<void()>{[] {}});
deduceArgs(Function<void(int, float)>{[](int, float) {}});
......
......@@ -417,54 +417,54 @@ int main(int argc, char** argv) {
============================================================================
folly/test/function_benchmark/main.cpp relative time/iter iters/s
============================================================================
fn_invoke 1.21ns 825.86M
fn_ptr_invoke 1.24ns 809.24M
std_function_invoke 2.76ns 362.09M
Function_invoke 2.75ns 364.02M
mem_fn_invoke 1.22ns 821.10M
fn_ptr_invoke_through_inline 1.21ns 826.38M
lambda_invoke_fn 1.22ns 821.00M
fn_invoke 1.22ns 822.88M
fn_ptr_invoke 1.22ns 822.99M
std_function_invoke 2.73ns 365.78M
Function_invoke 2.73ns 365.79M
mem_fn_invoke 1.37ns 731.38M
fn_ptr_invoke_through_inline 1.22ns 822.95M
lambda_invoke_fn 1.22ns 822.88M
lambda_noop 0.00fs Infinity
lambda_local_var 195.77ps 5.11G
fn_ptr_invoke_through_template 1.22ns 819.76M
virtual_fn_invoke 1.21ns 826.17M
fn_ptr_create_invoke 1.21ns 826.90M
std_function_create_invoke 3.72ns 268.86M
Function_create_invoke 2.80ns 357.04M
mem_fn_create_invoke 1.21ns 826.38M
std_bind_create_invoke 19.03ns 52.55M
std_bind_direct_invoke 1.21ns 824.20M
scope_guard_std_function 7.28ns 137.42M
scope_guard_std_function_rvalue 6.60ns 151.52M
scope_guard_Function_rvalue 4.93ns 202.65M
scope_guard_fn_ptr 1.23ns 815.68M
lambda_local_var 182.49ps 5.48G
fn_ptr_invoke_through_template 1.22ns 822.95M
virtual_fn_invoke 1.22ns 822.98M
fn_ptr_create_invoke 1.22ns 822.94M
std_function_create_invoke 3.88ns 257.83M
Function_create_invoke 2.73ns 365.73M
mem_fn_create_invoke 1.22ns 822.98M
std_bind_create_invoke 18.91ns 52.89M
std_bind_direct_invoke 1.22ns 822.98M
scope_guard_std_function 7.24ns 138.14M
scope_guard_std_function_rvalue 6.44ns 155.23M
scope_guard_Function_rvalue 5.53ns 180.87M
scope_guard_fn_ptr 928.25ps 1.08G
scope_guard_lambda_noop 0.00fs Infinity
scope_guard_lambda_function 1.24ns 807.24M
scope_guard_lambda_local_var 89.99ps 11.11G
scope_guard_lambda_function 1.22ns 822.97M
scope_guard_lambda_local_var 101.27ps 9.87G
----------------------------------------------------------------------------
throw_exception 1.91us 523.99K
catch_no_exception 1.22ns 820.79M
return_exc_ptr 1.40us 713.05K
exc_ptr_param_return 1.42us 704.62K
exc_ptr_param_return_null 1.21ns 826.90M
return_string 2.75ns 364.14M
return_string_noexcept 2.74ns 365.15M
return_code 903.47ps 1.11G
return_code_noexcept 1.21ns 823.26M
throw_exception 1.90us 524.98K
catch_no_exception 1.22ns 822.98M
return_exc_ptr 1.39us 719.84K
exc_ptr_param_return 1.41us 711.08K
exc_ptr_param_return_null 1.82ns 548.61M
return_string 2.43ns 411.48M
return_string_noexcept 2.43ns 411.48M
return_code 1.22ns 822.98M
return_code_noexcept 943.51ps 1.06G
----------------------------------------------------------------------------
std_function_create_move_invoke 53.45ns 18.71M
Function_create_move_invoke 50.59ns 19.77M
std_function_create_move_invoke_small 6.89ns 145.19M
Function_create_move_invoke_small 7.04ns 141.96M
std_function_create_move_invoke_ref 6.74ns 148.43M
Function_create_move_invoke_ref 6.93ns 144.39M
std_function_create_move_invoke 48.74ns 20.52M
Function_create_move_invoke 50.21ns 19.92M
std_function_create_move_invoke_small 6.78ns 147.58M
Function_create_move_invoke_small 7.01ns 142.67M
std_function_create_move_invoke_ref 6.67ns 150.03M
Function_create_move_invoke_ref 6.88ns 145.35M
----------------------------------------------------------------------------
function_ptr_move 1.21ns 825.65M
std_function_move_small 5.82ns 171.96M
Function_move_small 8.34ns 119.90M
std_function_move_small_trivial 5.79ns 172.70M
Function_move_small_trivial 6.68ns 149.72M
std_function_move_large 5.79ns 172.59M
Function_move_large 6.00ns 166.78M
function_ptr_move 1.21ns 823.05M
std_function_move_small 5.77ns 173.20M
Function_move_small 7.60ns 131.58M
std_function_move_small_trivial 5.77ns 173.27M
Function_move_small_trivial 5.47ns 182.86M
std_function_move_large 5.77ns 173.22M
Function_move_large 6.38ns 156.63M
============================================================================
*/
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