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

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: Move internal bits to base::internal, fix leaks 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/weak_ptr.h"
17
18 ///////////////////////////////////////////////////////////////////////////////
awong 2013/08/29 19:30:48 nit: Can we remove the /////// borders? None of t
Cait (Slow) 2013/08/30 00:28:02 Done.
19 //
20 // OVERVIEW:
21 //
22 // A container for a list of callbacks. Unlike a normal STL vector or list,
23 // this container can be modified during iteration without invalidating the
24 // iterator. So, it safely handles the case of an callback removing itself
25 // or other callback from the list while callbacks are being run.
26 //
27 // TYPICAL USAGE:
28 //
29 // class MyWidget {
30 // public:
31 // ...
32 //
33 // typedef base::Callback<void(const Foo&)> OnFooCallback;
34 //
35 // base::Closure RegisterCallback(const OnFooCallback& cb) {
36 // return callback_list_.Add(cb);
37 // }
38 //
39 // private:
40 // void NotifyFoo(const Foo& foo) {
41 // callback_list_.Run(foo);
42 // }
43 //
44 // CallbackList<Foo> callback_list_(CallbackList<Foo>::NOTIFY_ALL);
45 // };
46 //
47 //
48 // class MyWidgetListener {
49 // public:
50 //
awong 2013/08/29 19:30:48 nit: spurious newline.
Cait (Slow) 2013/08/30 00:28:02 Done.
51 // MyWidgetListener::MyWidgetListener() {
52 // // TODO (caitkp): A less clunky approach here?
53 // remove_foo_callback_.reset(new base::ScopedClosureRunner(
Avi (use Gerrit) 2013/08/29 16:22:58 :( It would be nice if you could do what scoped_pt
awong 2013/08/29 19:30:48 Yeah...we shouldn't need to scoped_ptr<> a Scoper.
Cait (Slow) 2013/08/30 00:28:02 Done.
54 // MyWidget::GetCurrent()->RegisterCallback(
55 // base::Bind(&MyWidgetListener::OnFoo, this))));
56 // }
57 //
58 // MyWidgetListener::~MyWidgetListener() {
59 // // ScopedClosureRunner runs its closure automatically on deletion.
60 // }
61 //
62 // void OnFoo(const Foo& foo) {
63 // // Do something.
64 // }
65 //
66 // private:
67 // scoped_ptr<base::ScopedClosureRunner> remove_foo_callback_;
68 // };
69 //
70 ///////////////////////////////////////////////////////////////////////////////
71
72 namespace base {
73
74 template <typename Detail>
75 class CallbackListWithDetails : public internal::CallbackListBase {
awong 2013/08/29 19:30:48 Sorry to keep churning this, but it occurs to me w
Cait (Slow) 2013/08/30 00:28:02 Done -- where should the NotificationType enum liv
76 public:
77 typedef base::Callback<void(const Detail&)> CallbackType;
78 typedef internal::CallbackListBase::NotificationType NotificationType;
79
80 explicit CallbackListWithDetails(NotificationType type)
81 : CallbackListBase(type) {}
82
83 virtual ~CallbackListWithDetails() {}
awong 2013/08/29 19:30:48 Kill off the virtual destructors?
Cait (Slow) 2013/08/30 00:28:02 Done.
84
85 // Add a callback to the list. A callback should not be added to
86 // the same list more than once. The returned closure (used to remove the
87 // callback from the list) is guaranteed to be safe to run.
88 base::Closure Add(const CallbackType& cb) {
89 DCHECK(!cb.is_null());
90 return AddCallback(new CallbackType(cb));
91 }
92
93 // Execute all active (non-null) callbacks with |details| parameter.
94 void Run(const Detail& details) {
95 if (might_have_callbacks()) {
96 CallbackListBase::Iterator it(this);
97 CallbackType* cb;
98 while((cb = static_cast<CallbackType*>(it.GetNext())) != NULL) {
99 cb->Run(details);
100 }
101 }
102 }
103
104 private:
105 DISALLOW_COPY_AND_ASSIGN(CallbackListWithDetails);
106 };
107
108 class CallbackList : public internal::CallbackListBase {
109 public:
110 typedef base::Closure CallbackType;
111 typedef CallbackListBase::NotificationType NotificationType;
112
113 explicit CallbackList(NotificationType type)
114 : CallbackListBase(type) {}
115
116 virtual ~CallbackList() {}
awong 2013/08/29 19:30:48 no virtual?
Cait (Slow) 2013/08/30 00:28:02 Done.
117
118 // Add a callback to the list. A callback should not be added to
119 // the same list more than once. The returned closure (used to remove the
120 // callback from the list) is guaranteed to be safe to run.
121 base::Closure Add(const base::Closure& cb) {
122 DCHECK(!cb.is_null());
123 return AddCallback(new CallbackType(cb));
124 }
125
126 // Execute all active (non-null) callbacks.
127 void Run() {
128 if (might_have_callbacks()) {
129 CallbackListBase::Iterator it(this);
130 CallbackType* cb;
131 while((cb = static_cast<CallbackType*>(it.GetNext())) != NULL) {
132 cb->Run();
133 }
134 }
135 }
136
137 private:
138 DISALLOW_COPY_AND_ASSIGN(CallbackList);
139 };
140
141 } // namespace base
142
143 #endif // BASE_CALLBACK_LIST_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698