diff options
author | davidben <davidben@chromium.org> | 2015-10-30 13:42:07 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-30 20:42:48 +0000 |
commit | f126cb2007e7d20764aeb4d4a41f3061010d4ee4 (patch) | |
tree | ce2a030922c806afaecd42d1744c8aaebdc5972d /base | |
parent | 233d38f9d8300b4078789bfe303c022e159335a7 (diff) | |
download | chromium_src-f126cb2007e7d20764aeb4d4a41f3061010d4ee4.zip chromium_src-f126cb2007e7d20764aeb4d4a41f3061010d4ee4.tar.gz chromium_src-f126cb2007e7d20764aeb4d4a41f3061010d4ee4.tar.bz2 |
Only signal the removal callback once in CallbackList::Compact.
Noticed this typo on a whim. Right now it signals it once for every registered
callback (removed or not) after the first removed one.
BUG=none
Review URL: https://codereview.chromium.org/1420053007
Cr-Commit-Position: refs/heads/master@{#357188}
Diffstat (limited to 'base')
-rw-r--r-- | base/callback_list.h | 6 | ||||
-rw-r--r-- | base/callback_list_unittest.cc | 45 |
2 files changed, 48 insertions, 3 deletions
diff --git a/base/callback_list.h b/base/callback_list.h index aeed5f1..5f263f8 100644 --- a/base/callback_list.h +++ b/base/callback_list.h @@ -185,10 +185,10 @@ class CallbackListBase { } else { ++it; } - - if (updated && !removal_callback_.is_null()) - removal_callback_.Run(); } + + if (updated && !removal_callback_.is_null()) + removal_callback_.Run(); } private: diff --git a/base/callback_list_unittest.cc b/base/callback_list_unittest.cc index 9adbabb..1cae827 100644 --- a/base/callback_list_unittest.cc +++ b/base/callback_list_unittest.cc @@ -98,6 +98,19 @@ class Summer { DISALLOW_COPY_AND_ASSIGN(Summer); }; +class Counter { + public: + Counter() : value_(0) {} + + void Increment() { value_++; } + + int value() const { return value_; } + + private: + int value_; + DISALLOW_COPY_AND_ASSIGN(Counter); +}; + // Sanity check that we can instantiate a CallbackList for each arity. TEST(CallbackListTest, ArityTest) { Summer s; @@ -287,5 +300,37 @@ TEST(CallbackListTest, EmptyList) { cb_reg.Notify(); } +TEST(CallbackList, RemovalCallback) { + Counter remove_count; + CallbackList<void(void)> cb_reg; + cb_reg.set_removal_callback( + Bind(&Counter::Increment, Unretained(&remove_count))); + + scoped_ptr<CallbackList<void(void)>::Subscription> subscription = + cb_reg.Add(Bind(&DoNothing)); + + // Removing a subscription outside of iteration signals the callback. + EXPECT_EQ(0, remove_count.value()); + subscription.reset(); + EXPECT_EQ(1, remove_count.value()); + + // Configure two subscriptions to remove themselves. + Remover remover_1, remover_2; + scoped_ptr<CallbackList<void(void)>::Subscription> remover_1_sub = + cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, + Unretained(&remover_1))); + scoped_ptr<CallbackList<void(void)>::Subscription> remover_2_sub = + cb_reg.Add(Bind(&Remover::IncrementTotalAndRemove, + Unretained(&remover_2))); + remover_1.SetSubscriptionToRemove(remover_1_sub.Pass()); + remover_2.SetSubscriptionToRemove(remover_2_sub.Pass()); + + // The callback should be signaled exactly once. + EXPECT_EQ(1, remove_count.value()); + cb_reg.Notify(); + EXPECT_EQ(2, remove_count.value()); + EXPECT_TRUE(cb_reg.empty()); +} + } // namespace } // namespace base |