Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(671)

Side by Side Diff: base/callback_list.h

Issue 22877038: Add a CallbackRegistry class to base/ to manage callbacks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Much clean up and removal of unneeded bits Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CALLBACK_LIST_H_
6 #define BASE_CALLBACK_LIST_H_
7
8 #include <algorithm>
9 #include <limits>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/callback_list_internal.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h"
18
19 // OVERVIEW:
20 //
21 // A container for a list of callbacks. Unlike a normal STL vector or list,
22 // this container can be modified during iteration without invalidating the
23 // iterator. It safely handles the case of a callback removing itself
24 // or another callback from the list while callbacks are being run.
25 //
26 // TYPICAL USAGE:
27 //
28 // class MyWidget {
29 // public:
30 // ...
31 //
32 // typedef base::Callback<void(const Foo&)> OnFooCallback;
33 //
34 // base::Closure RegisterCallback(const OnFooCallback& cb) {
35 // return callback_list_.Add(cb);
36 // }
37 //
38 // private:
39 // void NotifyFoo(const Foo& foo) {
40 // callback_list_.Run(foo);
41 // }
42 //
43 // CallbackList<Foo> callback_list_(CallbackList<Foo>::NOTIFY_ALL);
44 // };
45 //
46 //
47 // class MyWidgetListener {
48 // public:
49 // MyWidgetListener::MyWidgetListener() {
50 // remove_foo_callback_.Reset(
51 // MyWidget::GetCurrent()->RegisterCallback(
52 // base::Bind(&MyWidgetListener::OnFoo, this)));
53 // }
54 //
55 // MyWidgetListener::~MyWidgetListener() {
56 // // ScopedClosureRunner runs its closure automatically on deletion.
57 // }
58 //
59 // void OnFoo(const Foo& foo) {
60 // // Do something.
61 // }
62 //
63 // private:
64 // base::ScopedClosureRunner remove_foo_callback_;
65 // };
66
67 namespace base {
68
69 template <typename CallbackType>
70 class CallbackListBase {
awong 2013/09/04 23:20:07 CallbackListBase should be in base::internal.
Cait (Slow) 2013/09/06 18:41:46 Done.
71 public:
72 // Add a callback to the list. A callback should not be added to
73 // the same list more than once. The returned closure (used to remove the
74 // callback from the list) is guaranteed to be safe to run.
75 base::Closure Add(const CallbackType& cb) WARN_UNUSED_RESULT {
awong 2013/09/04 23:20:07 I'm going to slightly disagree with erikwright her
erikwright (departed) 2013/09/05 14:14:31 AIUI, the general model is publisher lifetime exce
Avi (use Gerrit) 2013/09/05 15:03:48 Or a ScopedClosureRunner? Same basic philosophy as
awong 2013/09/05 17:42:17 I see what you're saying but I'm not completely co
76 DCHECK(!cb.is_null());
77 return list_impl_.Add(new CallbackType(cb));
78 }
79
80 // Delete all callbacks in the list.
81 void Clear() {
82 list_impl_.Clear();
83 }
84
85 // Assert that the list is empty and no iterators are active.
86 void AssertEmpty() {
87 list_impl_.AssertEmpty();
88 }
89
90 protected:
91 CallbackListBase() {}
92
93 // Get an iterator to the CallbackList.
94 scoped_ptr<internal::CallbackListImpl::Iterator> GetIterator() {
95 return list_impl_.GetIterator();
96 }
97
98 private:
99 base::internal::CallbackListImpl list_impl_;
100
101 DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
102 };
103
104 template <typename Details>
105 class CallbackList : public CallbackListBase<Callback<void(const Details&)> > {
106 public:
107 typedef base::Callback<void(const Details&)> CallbackType;
108
109 CallbackList() : CallbackListBase<CallbackType>() {}
awong 2013/09/04 23:20:07 There's no need to explicitly call the default con
Cait (Slow) 2013/09/06 18:41:46 Done.
110
111 // Execute all active callbacks with |details| parameter.
112 void Run(const Details& details) {
113 scoped_ptr<internal::CallbackListImpl::Iterator> it = this->GetIterator();
awong 2013/09/04 23:20:07 indentation.
Cait (Slow) 2013/09/06 18:41:46 Done.
114 CallbackType* cb;
115 // static_cast is safe here, all callbacks were added via
awong 2013/09/04 23:20:07 here, all -> here. All
Cait (Slow) 2013/09/06 18:41:46 Done.
116 // CallbackListBase::Add and so must be of type
awong 2013/09/04 23:20:07 ::Add -> ::Add()
Cait (Slow) 2013/09/06 18:41:46 Done.
117 // Callback<void(const Details&)>.
118 while((cb = static_cast<CallbackType*>(it->GetNext())) !=
awong 2013/09/04 23:20:07 This can fit on one line.
Cait (Slow) 2013/09/06 18:41:46 Done.
119 NULL) {
120 cb->Run(details);
121 }
122 }
123
124 private:
125 DISALLOW_COPY_AND_ASSIGN(CallbackList);
126 };
127
128 template <> class CallbackList<void> : public CallbackListBase<Closure> {
129 public:
130 CallbackList() : CallbackListBase<Closure>() {}
awong 2013/09/04 23:20:07 Remove explicit invocation of base class's default
Cait (Slow) 2013/09/06 18:41:46 Done.
131
132 // Execute all active callbacks.
133 void Run() {
134 scoped_ptr<internal::CallbackListImpl::Iterator> it = GetIterator();
135 Closure* cb;
136 // static_cast is safe here, all callbacks were added via
awong 2013/09/04 23:20:07 here, all -> here. All
Cait (Slow) 2013/09/06 18:41:46 Done.
137 // CallbackListBase::Add and so must be Closures.
138 while((cb = static_cast<Closure*>(it->GetNext())) != NULL) {
139 cb->Run();
140 }
141 }
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(CallbackList);
145 };
146
147 } // namespace base
148
149 #endif // BASE_CALLBACK_LIST_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698