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

Side by Side Diff: base/callback_registry.h.pump

Issue 24648002: Rename CallbackRegistry to CallbackList (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Doc fix Created 7 years, 2 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
« no previous file with comments | « base/callback_registry.h ('k') | base/callback_registry_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 $$ This is a pump file for generating file templates. Pump is a python
2 $$ script that is part of the Google Test suite of utilities. Description
3 $$ can be found here:
4 $$
5 $$ http://code.google.com/p/googletest/wiki/PumpManual
6 $$
7
8 $$ See comment for MAX_ARITY in base/bind.h.pump.
9 $var MAX_ARITY = 7
10
11 // Copyright 2013 The Chromium Authors. All rights reserved.
12 // Use of this source code is governed by a BSD-style license that can be
13 // found in the LICENSE file.
14
15 #ifndef BASE_CALLBACK_REGISTRY_H_
16 #define BASE_CALLBACK_REGISTRY_H_
17
18 #include <list>
19
20 #include "base/basictypes.h"
21 #include "base/callback.h"
22 #include "base/callback_internal.h"
23 #include "base/compiler_specific.h"
24 #include "base/logging.h"
25 #include "base/memory/scoped_ptr.h"
26
27 // OVERVIEW:
28 //
29 // A container for a list of callbacks. Unlike a normal STL vector or list,
30 // this container can be modified during iteration without invalidating the
31 // iterator. It safely handles the case of a callback removing itself
32 // or another callback from the list while callbacks are being run.
33 //
34 // TYPICAL USAGE:
35 //
36 // class MyWidget {
37 // public:
38 // ...
39 //
40 // typedef base::Callback<void(const Foo&)> OnFooCallback;
41 //
42 // scoped_ptr<base::CallbackRegistry<void(const Foo&)>::Subscription>
43 // RegisterCallback(const OnFooCallback& cb) {
44 // return callback_registry_.Add(cb);
45 // }
46 //
47 // private:
48 // void NotifyFoo(const Foo& foo) {
49 // callback_registry_.Notify(foo);
50 // }
51 //
52 // base::CallbackRegistry<void(const Foo&)> callback_registry_;
53 // };
54 //
55 //
56 // class MyWidgetListener {
57 // public:
58 // MyWidgetListener::MyWidgetListener() {
59 // foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
60 // base::Bind(&MyWidgetListener::OnFoo, this)));
61 // }
62 //
63 // MyWidgetListener::~MyWidgetListener() {
64 // // Subscription gets deleted automatically and will deregister
65 // // the callback in the process.
66 // }
67 //
68 // private:
69 // void OnFoo(const Foo& foo) {
70 // // Do something.
71 // }
72 //
73 // scoped_ptr<base::CallbackRegistry<Foo>::Subscription> foo_subscription_;
74 // };
75
76 namespace base {
77
78 namespace internal {
79
80 template <typename CallbackType>
81 class CallbackRegistryBase {
82 public:
83 class Subscription {
84 public:
85 Subscription(CallbackRegistryBase<CallbackType>* list,
86 typename std::list<CallbackType>::iterator iter)
87 : list_(list),
88 iter_(iter) {}
89
90 ~Subscription() {
91 if (list_->active_iterator_count_)
92 (*iter_).Reset();
93 else
94 list_->callbacks_.erase(iter_);
95 }
96
97 private:
98 CallbackRegistryBase<CallbackType>* list_;
99 typename std::list<CallbackType>::iterator iter_;
100
101 DISALLOW_COPY_AND_ASSIGN(Subscription);
102 };
103
104 // Add a callback to the list. The callback will remain registered until the
105 // returned Subscription is destroyed, which must occur before the
106 // CallbackRegistry is destroyed.
107 scoped_ptr<Subscription> Add(const CallbackType& cb) {
108 DCHECK(!cb.is_null());
109 return scoped_ptr<Subscription>(
110 new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
111 }
112
113 protected:
114 // An iterator class that can be used to access the list of callbacks.
115 class Iterator {
116 public:
117 explicit Iterator(CallbackRegistryBase<CallbackType>* list)
118 : list_(list),
119 list_iter_(list_->callbacks_.begin()) {
120 ++list_->active_iterator_count_;
121 }
122
123 Iterator(const Iterator& iter)
124 : list_(iter.list_),
125 list_iter_(iter.list_iter_) {
126 ++list_->active_iterator_count_;
127 }
128
129 ~Iterator() {
130 if (list_ && --list_->active_iterator_count_ == 0) {
131 list_->Compact();
132 }
133 }
134
135 CallbackType* GetNext() {
136 while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
137 ++list_iter_;
138
139 CallbackType* cb = NULL;
140 if (list_iter_ != list_->callbacks_.end()) {
141 cb = &(*list_iter_);
142 ++list_iter_;
143 }
144 return cb;
145 }
146
147 private:
148 CallbackRegistryBase<CallbackType>* list_;
149 typename std::list<CallbackType>::iterator list_iter_;
150 };
151
152 CallbackRegistryBase()
153 : active_iterator_count_(0) {}
154
155 ~CallbackRegistryBase() {
156 DCHECK_EQ(0, active_iterator_count_);
157 DCHECK_EQ(0U, callbacks_.size());
158 }
159
160 // Returns an instance of a CallbackRegistryBase::Iterator which can be used
161 // to run callbacks.
162 Iterator GetIterator() {
163 return Iterator(this);
164 }
165
166 // Compact the list: remove any entries which were NULLed out during
167 // iteration.
168 void Compact() {
169 typename std::list<CallbackType>::iterator it = callbacks_.begin();
170 while (it != callbacks_.end()) {
171 if ((*it).is_null())
172 it = callbacks_.erase(it);
173 else
174 ++it;
175 }
176 }
177
178 private:
179 std::list<CallbackType> callbacks_;
180 int active_iterator_count_;
181
182 DISALLOW_COPY_AND_ASSIGN(CallbackRegistryBase);
183 };
184
185 } // namespace internal
186
187 template <typename Sig> class CallbackRegistry;
188
189
190 $range ARITY 0..MAX_ARITY
191 $for ARITY [[
192 $range ARG 1..ARITY
193
194 $if ARITY == 0 [[
195 template <>
196 class CallbackRegistry<void(void)>
197 : public internal::CallbackRegistryBase<Callback<void(void)> > {
198 ]] $else [[
199 template <$for ARG , [[typename A$(ARG)]]>
200 class CallbackRegistry<void($for ARG , [[A$(ARG)]])>
201 : public internal::CallbackRegistryBase<
202 Callback<void($for ARG , [[A$(ARG)]])> > {
203 ]]
204
205 public:
206 $if ARITY == 0 [[
207
208 typedef Callback<void(void)> CallbackType;
209 ]] $else [[
210
211 typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType;
212 ]]
213
214
215 CallbackRegistry() {}
216
217 void Notify($for ARG ,
218 [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$( ARG)]]) {
219 $if ARITY == 0 [[
220
221 internal::CallbackRegistryBase<CallbackType>::Iterator it =
222 this->GetIterator();
223 ]] $else [[
224
225 typename internal::CallbackRegistryBase<CallbackType>::Iterator it =
226 this->GetIterator();
227 ]]
228
229 CallbackType* cb;
230 while((cb = it.GetNext()) != NULL) {
231 cb->Run($for ARG , [[a$(ARG)]]);
232 }
233 }
234
235 private:
236 DISALLOW_COPY_AND_ASSIGN(CallbackRegistry);
237 };
238
239
240 ]] $$ for ARITY
241 } // namespace base
242
243 #endif // BASE_CALLBACK_REGISTRY_H
OLDNEW
« no previous file with comments | « base/callback_registry.h ('k') | base/callback_registry_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698