1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013
2 // Google Inc. All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
32 #define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
35 #if defined(BASE_CALLBACK_LIST_H_)
36 // Do nothing if the Chromium header has already been included.
37 // This can happen in cases where Chromium code is used directly by the
38 // client application. When using Chromium code directly always include
39 // the Chromium header first to avoid type conflicts.
40 #elif defined(BUILDING_CEF_SHARED)
41 // When building CEF include the Chromium header directly.
42 #include "base/callback_list.h"
43 #else // !BUILDING_CEF_SHARED
44 // The following is substantially similar to the Chromium implementation.
45 // If the Chromium implementation diverges the below implementation should be
50 #include "include/base/cef_basictypes.h"
51 #include "include/base/cef_callback.h"
52 #include "include/base/internal/cef_callback_internal.h"
53 #include "include/base/cef_build.h"
54 #include "include/base/cef_logging.h"
55 #include "include/base/cef_macros.h"
56 #include "include/base/cef_scoped_ptr.h"
60 // A container for a list of callbacks. Unlike a normal STL vector or list,
61 // this container can be modified during iteration without invalidating the
62 // iterator. It safely handles the case of a callback removing itself
63 // or another callback from the list while callbacks are being run.
71 // typedef base::Callback<void(const Foo&)> OnFooCallback;
73 // scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
74 // RegisterCallback(const OnFooCallback& cb) {
75 // return callback_list_.Add(cb);
79 // void NotifyFoo(const Foo& foo) {
80 // callback_list_.Notify(foo);
83 // base::CallbackList<void(const Foo&)> callback_list_;
85 // DISALLOW_COPY_AND_ASSIGN(MyWidget);
89 // class MyWidgetListener {
91 // MyWidgetListener::MyWidgetListener() {
92 // foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
93 // base::Bind(&MyWidgetListener::OnFoo, this)));
96 // MyWidgetListener::~MyWidgetListener() {
97 // // Subscription gets deleted automatically and will deregister
98 // // the callback in the process.
102 // void OnFoo(const Foo& foo) {
106 // scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
107 // foo_subscription_;
109 // DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
114 namespace cef_internal {
116 template <typename CallbackType>
117 class CallbackListBase {
121 Subscription(CallbackListBase<CallbackType>* list,
122 typename std::list<CallbackType>::iterator iter)
128 if (list_->active_iterator_count_) {
131 list_->callbacks_.erase(iter_);
132 if (!list_->removal_callback_.is_null())
133 list_->removal_callback_.Run();
138 CallbackListBase<CallbackType>* list_;
139 typename std::list<CallbackType>::iterator iter_;
141 DISALLOW_COPY_AND_ASSIGN(Subscription);
144 // Add a callback to the list. The callback will remain registered until the
145 // returned Subscription is destroyed, which must occur before the
146 // CallbackList is destroyed.
147 scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
148 DCHECK(!cb.is_null());
149 return scoped_ptr<Subscription>(
150 new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
153 // Sets a callback which will be run when a subscription list is changed.
154 void set_removal_callback(const Closure& callback) {
155 removal_callback_ = callback;
158 // Returns true if there are no subscriptions. This is only valid to call when
159 // not looping through the list.
161 DCHECK_EQ(0, active_iterator_count_);
162 return callbacks_.empty();
166 // An iterator class that can be used to access the list of callbacks.
169 explicit Iterator(CallbackListBase<CallbackType>* list)
171 list_iter_(list_->callbacks_.begin()) {
172 ++list_->active_iterator_count_;
175 Iterator(const Iterator& iter)
177 list_iter_(iter.list_iter_) {
178 ++list_->active_iterator_count_;
182 if (list_ && --list_->active_iterator_count_ == 0) {
187 CallbackType* GetNext() {
188 while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
191 CallbackType* cb = NULL;
192 if (list_iter_ != list_->callbacks_.end()) {
200 CallbackListBase<CallbackType>* list_;
201 typename std::list<CallbackType>::iterator list_iter_;
204 CallbackListBase() : active_iterator_count_(0) {}
206 ~CallbackListBase() {
207 DCHECK_EQ(0, active_iterator_count_);
208 DCHECK_EQ(0U, callbacks_.size());
211 // Returns an instance of a CallbackListBase::Iterator which can be used
213 Iterator GetIterator() {
214 return Iterator(this);
217 // Compact the list: remove any entries which were NULLed out during
220 typename std::list<CallbackType>::iterator it = callbacks_.begin();
221 bool updated = false;
222 while (it != callbacks_.end()) {
223 if ((*it).is_null()) {
225 it = callbacks_.erase(it);
230 if (updated && !removal_callback_.is_null())
231 removal_callback_.Run();
236 std::list<CallbackType> callbacks_;
237 int active_iterator_count_;
238 Closure removal_callback_;
240 DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
243 } // namespace cef_internal
245 template <typename Sig> class CallbackList;
248 class CallbackList<void(void)>
249 : public cef_internal::CallbackListBase<Callback<void(void)> > {
251 typedef Callback<void(void)> CallbackType;
256 cef_internal::CallbackListBase<CallbackType>::Iterator it =
259 while ((cb = it.GetNext()) != NULL) {
265 DISALLOW_COPY_AND_ASSIGN(CallbackList);
268 template <typename A1>
269 class CallbackList<void(A1)>
270 : public cef_internal::CallbackListBase<Callback<void(A1)> > {
272 typedef Callback<void(A1)> CallbackType;
276 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) {
277 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
280 while ((cb = it.GetNext()) != NULL) {
286 DISALLOW_COPY_AND_ASSIGN(CallbackList);
289 template <typename A1, typename A2>
290 class CallbackList<void(A1, A2)>
291 : public cef_internal::CallbackListBase<Callback<void(A1, A2)> > {
293 typedef Callback<void(A1, A2)> CallbackType;
297 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
298 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2) {
299 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
302 while ((cb = it.GetNext()) != NULL) {
308 DISALLOW_COPY_AND_ASSIGN(CallbackList);
311 template <typename A1, typename A2, typename A3>
312 class CallbackList<void(A1, A2, A3)>
313 : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3)> > {
315 typedef Callback<void(A1, A2, A3)> CallbackType;
319 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
320 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
321 typename cef_internal::CallbackParamTraits<A3>::ForwardType a3) {
322 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
325 while ((cb = it.GetNext()) != NULL) {
331 DISALLOW_COPY_AND_ASSIGN(CallbackList);
334 template <typename A1, typename A2, typename A3, typename A4>
335 class CallbackList<void(A1, A2, A3, A4)>
336 : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4)> > {
338 typedef Callback<void(A1, A2, A3, A4)> CallbackType;
342 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
343 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
344 typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
345 typename cef_internal::CallbackParamTraits<A4>::ForwardType a4) {
346 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
349 while ((cb = it.GetNext()) != NULL) {
350 cb->Run(a1, a2, a3, a4);
355 DISALLOW_COPY_AND_ASSIGN(CallbackList);
358 template <typename A1, typename A2, typename A3, typename A4, typename A5>
359 class CallbackList<void(A1, A2, A3, A4, A5)>
360 : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5)> > {
362 typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
366 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
367 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
368 typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
369 typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
370 typename cef_internal::CallbackParamTraits<A5>::ForwardType a5) {
371 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
374 while ((cb = it.GetNext()) != NULL) {
375 cb->Run(a1, a2, a3, a4, a5);
380 DISALLOW_COPY_AND_ASSIGN(CallbackList);
383 template <typename A1, typename A2, typename A3, typename A4, typename A5,
385 class CallbackList<void(A1, A2, A3, A4, A5, A6)>
386 : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5,
389 typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
393 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
394 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
395 typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
396 typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
397 typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
398 typename cef_internal::CallbackParamTraits<A6>::ForwardType a6) {
399 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
402 while ((cb = it.GetNext()) != NULL) {
403 cb->Run(a1, a2, a3, a4, a5, a6);
408 DISALLOW_COPY_AND_ASSIGN(CallbackList);
411 template <typename A1, typename A2, typename A3, typename A4, typename A5,
412 typename A6, typename A7>
413 class CallbackList<void(A1, A2, A3, A4, A5, A6, A7)>
414 : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5, A6,
417 typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
421 void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
422 typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
423 typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
424 typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
425 typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
426 typename cef_internal::CallbackParamTraits<A6>::ForwardType a6,
427 typename cef_internal::CallbackParamTraits<A7>::ForwardType a7) {
428 typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
431 while ((cb = it.GetNext()) != NULL) {
432 cb->Run(a1, a2, a3, a4, a5, a6, a7);
437 DISALLOW_COPY_AND_ASSIGN(CallbackList);
442 #endif // !BUILDING_CEF_SHARED
444 #endif // CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_