diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 1 | ||||
-rw-r--r-- | base/callback_registry.h | 213 | ||||
-rw-r--r-- | base/callback_registry.h.pump | 243 | ||||
-rw-r--r-- | base/callback_registry_unittest.cc | 116 | ||||
-rw-r--r-- | base/callback_registry_unittest.nc | 51 |
5 files changed, 578 insertions, 46 deletions
diff --git a/base/base.gyp b/base/base.gyp index 39f6015..fbc33b8 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -461,6 +461,7 @@ 'build_time_unittest.cc', 'callback_helpers_unittest.cc', 'callback_registry_unittest.cc', + 'callback_registry_unittest.nc', 'callback_unittest.cc', 'callback_unittest.nc', 'cancelable_callback_unittest.cc', diff --git a/base/callback_registry.h b/base/callback_registry.h index fcacbf5..dcdeb81 100644 --- a/base/callback_registry.h +++ b/base/callback_registry.h @@ -1,3 +1,8 @@ +// This file was GENERATED by command: +// pump.py callback_registry.h.pump +// DO NOT EDIT BY HAND!!! + + // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,6 +14,7 @@ #include "base/basictypes.h" #include "base/callback.h" +#include "base/callback_internal.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -28,8 +34,8 @@ // // typedef base::Callback<void(const Foo&)> OnFooCallback; // -// scoped_ptr<base::CallbackRegistry<Foo>::Subscription> RegisterCallback( -// const OnFooCallback& cb) { +// scoped_ptr<base::CallbackRegistry<void(const Foo&)>::Subscription> +// RegisterCallback(const OnFooCallback& cb) { // return callback_registry_.Add(cb); // } // @@ -38,7 +44,7 @@ // callback_registry_.Notify(foo); // } // -// base::CallbackRegistry<Foo> callback_registry_; +// base::CallbackRegistry<void(const Foo&)> callback_registry_; // }; // // @@ -59,7 +65,8 @@ // // Do something. // } // -// scoped_ptr<base::CallbackRegistry<Foo>::Subscription> foo_subscription_; +// scoped_ptr<base::CallbackRegistry<void(const Foo&)>::Subscription> +// foo_subscription_; // }; namespace base { @@ -173,37 +180,199 @@ class CallbackRegistryBase { } // namespace internal -template <typename Details> -class CallbackRegistry - : public internal::CallbackRegistryBase<Callback<void(const Details&)> > { +template <typename Sig> class CallbackRegistry; + +template <> +class CallbackRegistry<void(void)> + : public internal::CallbackRegistryBase<Callback<void(void)> > { public: + typedef Callback<void(void)> CallbackType; + CallbackRegistry() {} - // Execute all active callbacks with |details| parameter. - void Notify(const Details& details) { - typename internal::CallbackRegistryBase< - Callback<void(const Details&)> >::Iterator it = this->GetIterator(); - Callback<void(const Details&)>* cb; + void Notify() { + internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; while((cb = it.GetNext()) != NULL) { - cb->Run(details); + cb->Run(); } } -private: + private: DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); }; -template <> class CallbackRegistry<void> - : public internal::CallbackRegistryBase<Closure> { +template <typename A1> +class CallbackRegistry<void(A1)> + : public internal::CallbackRegistryBase< + Callback<void(A1)> > { public: + typedef Callback<void(A1)> CallbackType; + CallbackRegistry() {} - // Execute all active callbacks. - void Notify() { - Iterator it = this->GetIterator(); - Closure* cb; + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; while((cb = it.GetNext()) != NULL) { - cb->Run(); + cb->Run(a1); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2> +class CallbackRegistry<void(A1, A2)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2)> > { + public: + typedef Callback<void(A1, A2)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2, typename A3> +class CallbackRegistry<void(A1, A2, A3)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2, A3)> > { + public: + typedef Callback<void(A1, A2, A3)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2, typename A3, typename A4> +class CallbackRegistry<void(A1, A2, A3, A4)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2, A3, A4)> > { + public: + typedef Callback<void(A1, A2, A3, A4)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2, typename A3, typename A4, typename A5> +class CallbackRegistry<void(A1, A2, A3, A4, A5)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2, A3, A4, A5)> > { + public: + typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2, typename A3, typename A4, typename A5, + typename A6> +class CallbackRegistry<void(A1, A2, A3, A4, A5, A6)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2, A3, A4, A5, A6)> > { + public: + typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5, + typename internal::CallbackParamTraits<A6>::ForwardType a6) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5, a6); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + +template <typename A1, typename A2, typename A3, typename A4, typename A5, + typename A6, typename A7> +class CallbackRegistry<void(A1, A2, A3, A4, A5, A6, A7)> + : public internal::CallbackRegistryBase< + Callback<void(A1, A2, A3, A4, A5, A6, A7)> > { + public: + typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType; + + CallbackRegistry() {} + + void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5, + typename internal::CallbackParamTraits<A6>::ForwardType a6, + typename internal::CallbackParamTraits<A7>::ForwardType a7) { + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5, a6, a7); } } @@ -213,4 +382,4 @@ template <> class CallbackRegistry<void> } // namespace base -#endif // BASE_CALLBACK_REGISTRY_H_ +#endif // BASE_CALLBACK_REGISTRY_H diff --git a/base/callback_registry.h.pump b/base/callback_registry.h.pump new file mode 100644 index 0000000..fff1dc8 --- /dev/null +++ b/base/callback_registry.h.pump @@ -0,0 +1,243 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ + +$$ See comment for MAX_ARITY in base/bind.h.pump. +$var MAX_ARITY = 7 + +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CALLBACK_REGISTRY_H_ +#define BASE_CALLBACK_REGISTRY_H_ + +#include <list> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/callback_internal.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" + +// OVERVIEW: +// +// A container for a list of callbacks. Unlike a normal STL vector or list, +// this container can be modified during iteration without invalidating the +// iterator. It safely handles the case of a callback removing itself +// or another callback from the list while callbacks are being run. +// +// TYPICAL USAGE: +// +// class MyWidget { +// public: +// ... +// +// typedef base::Callback<void(const Foo&)> OnFooCallback; +// +// scoped_ptr<base::CallbackRegistry<void(const Foo&)>::Subscription> +// RegisterCallback(const OnFooCallback& cb) { +// return callback_registry_.Add(cb); +// } +// +// private: +// void NotifyFoo(const Foo& foo) { +// callback_registry_.Notify(foo); +// } +// +// base::CallbackRegistry<void(const Foo&)> callback_registry_; +// }; +// +// +// class MyWidgetListener { +// public: +// MyWidgetListener::MyWidgetListener() { +// foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback( +// base::Bind(&MyWidgetListener::OnFoo, this))); +// } +// +// MyWidgetListener::~MyWidgetListener() { +// // Subscription gets deleted automatically and will deregister +// // the callback in the process. +// } +// +// private: +// void OnFoo(const Foo& foo) { +// // Do something. +// } +// +// scoped_ptr<base::CallbackRegistry<Foo>::Subscription> foo_subscription_; +// }; + +namespace base { + +namespace internal { + +template <typename CallbackType> +class CallbackRegistryBase { + public: + class Subscription { + public: + Subscription(CallbackRegistryBase<CallbackType>* list, + typename std::list<CallbackType>::iterator iter) + : list_(list), + iter_(iter) {} + + ~Subscription() { + if (list_->active_iterator_count_) + (*iter_).Reset(); + else + list_->callbacks_.erase(iter_); + } + + private: + CallbackRegistryBase<CallbackType>* list_; + typename std::list<CallbackType>::iterator iter_; + + DISALLOW_COPY_AND_ASSIGN(Subscription); + }; + + // Add a callback to the list. The callback will remain registered until the + // returned Subscription is destroyed, which must occur before the + // CallbackRegistry is destroyed. + scoped_ptr<Subscription> Add(const CallbackType& cb) { + DCHECK(!cb.is_null()); + return scoped_ptr<Subscription>( + new Subscription(this, callbacks_.insert(callbacks_.end(), cb))); + } + + protected: + // An iterator class that can be used to access the list of callbacks. + class Iterator { + public: + explicit Iterator(CallbackRegistryBase<CallbackType>* list) + : list_(list), + list_iter_(list_->callbacks_.begin()) { + ++list_->active_iterator_count_; + } + + Iterator(const Iterator& iter) + : list_(iter.list_), + list_iter_(iter.list_iter_) { + ++list_->active_iterator_count_; + } + + ~Iterator() { + if (list_ && --list_->active_iterator_count_ == 0) { + list_->Compact(); + } + } + + CallbackType* GetNext() { + while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null()) + ++list_iter_; + + CallbackType* cb = NULL; + if (list_iter_ != list_->callbacks_.end()) { + cb = &(*list_iter_); + ++list_iter_; + } + return cb; + } + + private: + CallbackRegistryBase<CallbackType>* list_; + typename std::list<CallbackType>::iterator list_iter_; + }; + + CallbackRegistryBase() + : active_iterator_count_(0) {} + + ~CallbackRegistryBase() { + DCHECK_EQ(0, active_iterator_count_); + DCHECK_EQ(0U, callbacks_.size()); + } + + // Returns an instance of a CallbackRegistryBase::Iterator which can be used + // to run callbacks. + Iterator GetIterator() { + return Iterator(this); + } + + // Compact the list: remove any entries which were NULLed out during + // iteration. + void Compact() { + typename std::list<CallbackType>::iterator it = callbacks_.begin(); + while (it != callbacks_.end()) { + if ((*it).is_null()) + it = callbacks_.erase(it); + else + ++it; + } + } + + private: + std::list<CallbackType> callbacks_; + int active_iterator_count_; + + DISALLOW_COPY_AND_ASSIGN(CallbackRegistryBase); +}; + +} // namespace internal + +template <typename Sig> class CallbackRegistry; + + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +$if ARITY == 0 [[ +template <> +class CallbackRegistry<void(void)> + : public internal::CallbackRegistryBase<Callback<void(void)> > { +]] $else [[ +template <$for ARG , [[typename A$(ARG)]]> +class CallbackRegistry<void($for ARG , [[A$(ARG)]])> + : public internal::CallbackRegistryBase< + Callback<void($for ARG , [[A$(ARG)]])> > { +]] + + public: +$if ARITY == 0 [[ + + typedef Callback<void(void)> CallbackType; +]] $else [[ + + typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType; +]] + + + CallbackRegistry() {} + + void Notify($for ARG , + [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { +$if ARITY == 0 [[ + + internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); +]] $else [[ + + typename internal::CallbackRegistryBase<CallbackType>::Iterator it = + this->GetIterator(); +]] + + CallbackType* cb; + while((cb = it.GetNext()) != NULL) { + cb->Run($for ARG , [[a$(ARG)]]); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackRegistry); +}; + + +]] $$ for ARITY +} // namespace base + +#endif // BASE_CALLBACK_REGISTRY_H diff --git a/base/callback_registry_unittest.cc b/base/callback_registry_unittest.cc index 3459c07..826aa0d 100644 --- a/base/callback_registry_unittest.cc +++ b/base/callback_registry_unittest.cc @@ -18,7 +18,7 @@ class Listener { Listener() : total_(0), scaler_(1) {} explicit Listener(int scaler) : total_(0), scaler_(scaler) {} void IncrementTotal() { total_++; } - void IncrementByMultipleOfScaler(const int& x) { total_ += x * scaler_; } + void IncrementByMultipleOfScaler(int x) { total_ += x * scaler_; } int total_; @@ -35,20 +35,20 @@ class Remover { removal_subscription_.reset(); } void SetSubscriptionToRemove( - scoped_ptr<CallbackRegistry<void>::Subscription> sub) { + scoped_ptr<CallbackRegistry<void(void)>::Subscription> sub) { removal_subscription_ = sub.Pass(); } int total_; private: - scoped_ptr<CallbackRegistry<void>::Subscription> removal_subscription_; + scoped_ptr<CallbackRegistry<void(void)>::Subscription> removal_subscription_; DISALLOW_COPY_AND_ASSIGN(Remover); }; class Adder { public: - explicit Adder(CallbackRegistry<void>* cb_reg) + explicit Adder(CallbackRegistry<void(void)>* cb_reg) : added_(false), total_(0), cb_reg_(cb_reg) {} @@ -65,20 +65,88 @@ class Adder { int total_; private: - CallbackRegistry<void>* cb_reg_; - scoped_ptr<CallbackRegistry<void>::Subscription> subscription_; + CallbackRegistry<void(void)>* cb_reg_; + scoped_ptr<CallbackRegistry<void(void)>::Subscription> subscription_; DISALLOW_COPY_AND_ASSIGN(Adder); }; +class Summer { + public: + Summer() : value_(0) {} + + void AddOneParam(int a) { value_ = a; } + void AddTwoParam(int a, int b) { value_ = a + b; } + void AddThreeParam(int a, int b, int c) { value_ = a + b + c; } + void AddFourParam(int a, int b, int c, int d) { value_ = a + b + c + d; } + void AddFiveParam(int a, int b, int c, int d, int e) { + value_ = a + b + c + d + e; + } + void AddSixParam(int a, int b, int c, int d, int e , int f) { + value_ = a + b + c + d + e + f; + } + + int value_; + + private: + DISALLOW_COPY_AND_ASSIGN(Summer); +}; + +// Sanity check that we can instantiate a CallbackRegistry for each arity. +TEST(CallbackRegistryTest, ArityTest) { + Summer s; + + CallbackRegistry<void(int)> c1; + scoped_ptr<CallbackRegistry<void(int)>::Subscription> subscription1 = + c1.Add(Bind(&Summer::AddOneParam, Unretained(&s))); + + c1.Notify(1); + EXPECT_EQ(1, s.value_); + + CallbackRegistry<void(int, int)> c2; + scoped_ptr<CallbackRegistry<void(int, int)>::Subscription> subscription2 = + c2.Add(Bind(&Summer::AddTwoParam, Unretained(&s))); + + c2.Notify(1, 2); + EXPECT_EQ(3, s.value_); + + CallbackRegistry<void(int, int, int)> c3; + scoped_ptr<CallbackRegistry<void(int, int, int)>::Subscription> + subscription3 = c3.Add(Bind(&Summer::AddThreeParam, Unretained(&s))); + + c3.Notify(1, 2, 3); + EXPECT_EQ(6, s.value_); + + CallbackRegistry<void(int, int, int, int)> c4; + scoped_ptr<CallbackRegistry<void(int, int, int, int)>::Subscription> + subscription4 = c4.Add(Bind(&Summer::AddFourParam, Unretained(&s))); + + c4.Notify(1, 2, 3, 4); + EXPECT_EQ(10, s.value_); + + CallbackRegistry<void(int, int, int, int, int)> c5; + scoped_ptr<CallbackRegistry<void(int, int, int, int, int)>::Subscription> + subscription5 = c5.Add(Bind(&Summer::AddFiveParam, Unretained(&s))); + + c5.Notify(1, 2, 3, 4, 5); + EXPECT_EQ(15, s.value_); + + CallbackRegistry<void(int, int, int, int, int, int)> c6; + scoped_ptr<CallbackRegistry<void(int, int, int, int, int, int)>::Subscription> + subscription6 = c6.Add(Bind(&Summer::AddSixParam, Unretained(&s))); + + c6.Notify(1, 2, 3, 4, 5, 6); + EXPECT_EQ(21, s.value_); +} + // Sanity check that closures added to the list will be run, and those removed // from the list will not be run. TEST(CallbackRegistryTest, BasicTest) { - CallbackRegistry<void> cb_reg; + CallbackRegistry<void(void)> cb_reg; Listener a, b, c; - scoped_ptr<CallbackRegistry<void>::Subscription> a_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> a_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&a))); - scoped_ptr<CallbackRegistry<void>::Subscription> b_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> b_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b))); EXPECT_TRUE(a_subscription.get()); @@ -91,7 +159,7 @@ TEST(CallbackRegistryTest, BasicTest) { b_subscription.reset(); - scoped_ptr<CallbackRegistry<void>::Subscription> c_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> c_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&c))); cb_reg.Notify(); @@ -108,12 +176,12 @@ TEST(CallbackRegistryTest, BasicTest) { // Sanity check that callbacks with details added to the list will be run, with // the correct details, and those removed from the list will not be run. TEST(CallbackRegistryTest, BasicTestWithParams) { - CallbackRegistry<int> cb_reg; + CallbackRegistry<void(int)> cb_reg; Listener a(1), b(-1), c(1); - scoped_ptr<CallbackRegistry<int>::Subscription> a_subscription = + scoped_ptr<CallbackRegistry<void(int)>::Subscription> a_subscription = cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&a))); - scoped_ptr<CallbackRegistry<int>::Subscription> b_subscription = + scoped_ptr<CallbackRegistry<void(int)>::Subscription> b_subscription = cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&b))); EXPECT_TRUE(a_subscription.get()); @@ -126,7 +194,7 @@ TEST(CallbackRegistryTest, BasicTestWithParams) { b_subscription.reset(); - scoped_ptr<CallbackRegistry<int>::Subscription> c_subscription = + scoped_ptr<CallbackRegistry<void(int)>::Subscription> c_subscription = cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&c))); cb_reg.Notify(10); @@ -143,23 +211,23 @@ TEST(CallbackRegistryTest, BasicTestWithParams) { // Test the a callback can remove itself or a different callback from the list // during iteration without invalidating the iterator. TEST(CallbackRegistryTest, RemoveCallbacksDuringIteration) { - CallbackRegistry<void> cb_reg; + CallbackRegistry<void(void)> cb_reg; Listener a, b; Remover remover_1, remover_2; - scoped_ptr<CallbackRegistry<void>::Subscription> remover_1_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> remover_1_sub = cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_1))); - scoped_ptr<CallbackRegistry<void>::Subscription> remover_2_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> remover_2_sub = cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_2))); - scoped_ptr<CallbackRegistry<void>::Subscription> a_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> a_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&a))); - scoped_ptr<CallbackRegistry<void>::Subscription> b_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> b_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b))); // |remover_1| will remove itself. - remover_1.SetSubscriptionToRemove(remover_1_subscription.Pass()); + remover_1.SetSubscriptionToRemove(remover_1_sub.Pass()); // |remover_2| will remove a. remover_2.SetSubscriptionToRemove(a_subscription.Pass()); @@ -185,12 +253,12 @@ TEST(CallbackRegistryTest, RemoveCallbacksDuringIteration) { // without invalidating the iterator. The newly added callback should be run on // the current iteration as will all other callbacks in the list. TEST(CallbackRegistryTest, AddCallbacksDuringIteration) { - CallbackRegistry<void> cb_reg; + CallbackRegistry<void(void)> cb_reg; Adder a(&cb_reg); Listener b; - scoped_ptr<CallbackRegistry<void>::Subscription> a_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> a_subscription = cb_reg.Add(Bind(&Adder::AddCallback, Unretained(&a))); - scoped_ptr<CallbackRegistry<void>::Subscription> b_subscription = + scoped_ptr<CallbackRegistry<void(void)>::Subscription> b_subscription = cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b))); cb_reg.Notify(); @@ -207,7 +275,7 @@ TEST(CallbackRegistryTest, AddCallbacksDuringIteration) { // Sanity check: notifying an empty list is a no-op. TEST(CallbackRegistryTest, EmptyList) { - CallbackRegistry<void> cb_reg; + CallbackRegistry<void(void)> cb_reg; cb_reg.Notify(); } diff --git a/base/callback_registry_unittest.nc b/base/callback_registry_unittest.nc new file mode 100644 index 0000000..d67ad81 --- /dev/null +++ b/base/callback_registry_unittest.nc @@ -0,0 +1,51 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/callback_registry.h" + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/memory/scoped_ptr.h" + +namespace base { + +class Foo { + public: + Foo() {} + ~Foo() {} +}; + +class FooListener { + public: + FooListener() {} + + void GotAScopedFoo(scoped_ptr<Foo> f) { foo_ = f.Pass(); } + + scoped_ptr<Foo> foo_; + + private: + DISALLOW_COPY_AND_ASSIGN(FooListener); +}; + + +#if defined(NCTEST_MOVE_ONLY_TYPE_PARAMETER) // [r"calling a private constructor of class"] + +// Callbacks run with a move-only typed parameter. +// +// CallbackRegistry does not support move-only typed parameters. Notify() is +// designed to take zero or more parameters, and run each registered callback +// with them. With move-only types, the parameter will be set to NULL after the +// first callback has been run. +void WontCompile() { + FooListener f; + CallbackRegistry<void(scoped_ptr<Foo>)> c1; + scoped_ptr<CallbackRegistry<void(scoped_ptr<Foo>)>::Subscription> sub = + c1.Add(Bind(&FooListener::GotAScopedFoo, Unretained(&f))); + c1.Notify(scoped_ptr<Foo>(new Foo())); +} + +#endif + +} // namespace base |