Skip to content

Commit

Permalink
Revert 114494 - Remove BindStateHolder and have Bind() return a Callb…
Browse files Browse the repository at this point in the history
…ack<> object directly.

This removes some complexity and also fixes a bug where if you call Bind() with the result of Bind(), the resulting Callback would only be valid during the first call.  Ouch.

BUG=none
TEST=new unittests


Review URL: http://codereview.chromium.org/8738001

TBR=ajwong@chromium.org
Review URL: http://codereview.chromium.org/8914022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114495 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sail@chromium.org committed Dec 14, 2011
1 parent e91ac22 commit 1152886
Show file tree
Hide file tree
Showing 27 changed files with 281 additions and 342 deletions.
171 changes: 77 additions & 94 deletions base/bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@
namespace base {

template <typename Functor>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void()>
::UnboundRunType>
void()> >
Bind(Functor functor) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
Expand All @@ -61,20 +60,18 @@ Bind(Functor functor) {
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;

typedef internal::BindState<RunnableType, RunType, void()> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType, void()>(
internal::MakeRunnable(functor)));
}

template <typename Functor, typename P1>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)>
::UnboundRunType>
void(typename internal::CallbackParamTraits<P1>::StorageType)> >
Bind(Functor functor, const P1& p1) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
Expand Down Expand Up @@ -106,22 +103,20 @@ Bind(Functor functor, const P1& p1) {
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)>(
internal::MakeRunnable(functor), p1));
}

template <typename Functor, typename P1, typename P2>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P2>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
Expand Down Expand Up @@ -156,24 +151,22 @@ Bind(Functor functor, const P1& p1, const P2& p2) {
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)>(
internal::MakeRunnable(functor), p1, p2));
}

template <typename Functor, typename P1, typename P2, typename P3>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P3>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
Expand Down Expand Up @@ -211,26 +204,24 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)>(
internal::MakeRunnable(functor), p1, p2, p3));
}

template <typename Functor, typename P1, typename P2, typename P3, typename P4>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P4>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
Expand Down Expand Up @@ -271,29 +262,27 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)>(
internal::MakeRunnable(functor), p1, p2, p3, p4));
}

template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P5>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5) {
// Typedefs for how to store and run the functor.
Expand Down Expand Up @@ -338,31 +327,29 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)>(
internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
}

template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P6>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6) {
// Typedefs for how to store and run the functor.
Expand Down Expand Up @@ -410,23 +397,22 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)>(
internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
}

template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
Expand All @@ -435,8 +421,7 @@ base::Callback<
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)>
::UnboundRunType>
typename internal::CallbackParamTraits<P7>::StorageType)> >
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6, const P7& p7) {
// Typedefs for how to store and run the functor.
Expand Down Expand Up @@ -487,19 +472,17 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
p6_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
p7_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)> BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6,
p7));

return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)>(
internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, p7));
}

} // namespace base
Expand Down
17 changes: 7 additions & 10 deletions base/bind.h.pump
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,11 @@ $range ARG 1..ARITY

template <typename Functor[[]]
$if ARITY > 0 [[, ]] $for ARG , [[typename P$(ARG)]]>
base::Callback<
typename internal::BindState<
internal::BindStateHolder<
internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])>
::UnboundRunType>
void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> >
Bind(Functor functor
$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) {
// Typedefs for how to store and run the functor.
Expand Down Expand Up @@ -126,13 +125,11 @@ $if ARG == 1 [[

]] $$ $for ARG

typedef internal::BindState<RunnableType, RunType, [[]]
void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> [[]]
BindState;


return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)[[]]
return internal::MakeBindStateHolder(
new internal::BindState<RunnableType, RunType, [[]]
void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])>(
internal::MakeRunnable(functor)[[]]
$if ARITY > 0 [[, ]] $for ARG , [[p$(ARG)]]));
}

Expand Down
27 changes: 0 additions & 27 deletions base/bind_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,18 +199,10 @@ void RefArgSet(int &n) {
n = 2;
}

void PtrArgSet(int *n) {
*n = 2;
}

int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
return n;
}

void TakesACallback(const Closure& callback) {
callback.Run();
}

class BindTest : public ::testing::Test {
public:
BindTest() {
Expand Down Expand Up @@ -292,25 +284,6 @@ TEST_F(BindTest, CurryingTest) {
EXPECT_EQ(63, c0.Run());
}

// Test that currying the rvalue result of another Bind() works correctly.
// - rvalue should be usable as argument to Bind().
// - multiple runs of resulting Callback remain valid.
TEST_F(BindTest, CurryingRvalueResultOfBind) {
int n = 0;
Closure cb = base::Bind(&TakesACallback, base::Bind(&PtrArgSet, &n));

// If we implement Bind() such that the return value has auto_ptr-like
// semantics, the second call here will fail because ownership of
// the internal BindState<> would have been transfered to a *temporary*
// constructon of a Callback object on the first call.
cb.Run();
EXPECT_EQ(2, n);

n = 0;
cb.Run();
EXPECT_EQ(2, n);
}

// Function type support.
// - Normal function.
// - Normal function bound with non-refcounted first argument.
Expand Down
Loading

0 comments on commit 1152886

Please sign in to comment.