]> git.sesse.net Git - casparcg/blob - dependencies64/cef/include/base/cef_callback_list.h
* Merged html producer and updated to latest CEF version (does not have satisfactory...
[casparcg] / dependencies64 / cef / include / base / cef_callback_list.h
1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013
2 // Google Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
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
13 // distribution.
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.
18 //
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.
30
31 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
32 #define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
33 #pragma once
34
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
46 // updated to match.
47
48 #include <list>
49
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"
57
58 // OVERVIEW:
59 //
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.
64 //
65 // TYPICAL USAGE:
66 //
67 // class MyWidget {
68 //  public:
69 //   ...
70 //
71 //   typedef base::Callback<void(const Foo&)> OnFooCallback;
72 //
73 //   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
74 //   RegisterCallback(const OnFooCallback& cb) {
75 //     return callback_list_.Add(cb);
76 //   }
77 //
78 //  private:
79 //   void NotifyFoo(const Foo& foo) {
80 //      callback_list_.Notify(foo);
81 //   }
82 //
83 //   base::CallbackList<void(const Foo&)> callback_list_;
84 //
85 //   DISALLOW_COPY_AND_ASSIGN(MyWidget);
86 // };
87 //
88 //
89 // class MyWidgetListener {
90 //  public:
91 //   MyWidgetListener::MyWidgetListener() {
92 //     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
93 //             base::Bind(&MyWidgetListener::OnFoo, this)));
94 //   }
95 //
96 //   MyWidgetListener::~MyWidgetListener() {
97 //      // Subscription gets deleted automatically and will deregister
98 //      // the callback in the process.
99 //   }
100 //
101 //  private:
102 //   void OnFoo(const Foo& foo) {
103 //     // Do something.
104 //   }
105 //
106 //   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
107 //       foo_subscription_;
108 //
109 //   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
110 // };
111
112 namespace base {
113
114 namespace cef_internal {
115
116 template <typename CallbackType>
117 class CallbackListBase {
118  public:
119   class Subscription {
120    public:
121     Subscription(CallbackListBase<CallbackType>* list,
122                  typename std::list<CallbackType>::iterator iter)
123         : list_(list),
124           iter_(iter) {
125     }
126
127     ~Subscription() {
128       if (list_->active_iterator_count_) {
129         iter_->Reset();
130       } else {
131         list_->callbacks_.erase(iter_);
132         if (!list_->removal_callback_.is_null())
133           list_->removal_callback_.Run();
134       }
135     }
136
137    private:
138     CallbackListBase<CallbackType>* list_;
139     typename std::list<CallbackType>::iterator iter_;
140
141     DISALLOW_COPY_AND_ASSIGN(Subscription);
142   };
143
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)));
151   }
152
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;
156   }
157
158   // Returns true if there are no subscriptions. This is only valid to call when
159   // not looping through the list.
160   bool empty() {
161     DCHECK_EQ(0, active_iterator_count_);
162     return callbacks_.empty();
163   }
164
165  protected:
166   // An iterator class that can be used to access the list of callbacks.
167   class Iterator {
168    public:
169     explicit Iterator(CallbackListBase<CallbackType>* list)
170         : list_(list),
171           list_iter_(list_->callbacks_.begin()) {
172       ++list_->active_iterator_count_;
173     }
174
175     Iterator(const Iterator& iter)
176         : list_(iter.list_),
177           list_iter_(iter.list_iter_) {
178       ++list_->active_iterator_count_;
179     }
180
181     ~Iterator() {
182       if (list_ && --list_->active_iterator_count_ == 0) {
183         list_->Compact();
184       }
185     }
186
187     CallbackType* GetNext() {
188       while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
189         ++list_iter_;
190
191       CallbackType* cb = NULL;
192       if (list_iter_ != list_->callbacks_.end()) {
193         cb = &(*list_iter_);
194         ++list_iter_;
195       }
196       return cb;
197     }
198
199    private:
200     CallbackListBase<CallbackType>* list_;
201     typename std::list<CallbackType>::iterator list_iter_;
202   };
203
204   CallbackListBase() : active_iterator_count_(0) {}
205
206   ~CallbackListBase() {
207     DCHECK_EQ(0, active_iterator_count_);
208     DCHECK_EQ(0U, callbacks_.size());
209   }
210
211   // Returns an instance of a CallbackListBase::Iterator which can be used
212   // to run callbacks.
213   Iterator GetIterator() {
214     return Iterator(this);
215   }
216
217   // Compact the list: remove any entries which were NULLed out during
218   // iteration.
219   void Compact() {
220     typename std::list<CallbackType>::iterator it = callbacks_.begin();
221     bool updated = false;
222     while (it != callbacks_.end()) {
223       if ((*it).is_null()) {
224         updated = true;
225         it = callbacks_.erase(it);
226       } else {
227         ++it;
228       }
229
230       if (updated && !removal_callback_.is_null())
231         removal_callback_.Run();
232     }
233   }
234
235  private:
236   std::list<CallbackType> callbacks_;
237   int active_iterator_count_;
238   Closure removal_callback_;
239
240   DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
241 };
242
243 }  // namespace cef_internal
244
245 template <typename Sig> class CallbackList;
246
247 template <>
248 class CallbackList<void(void)>
249     : public cef_internal::CallbackListBase<Callback<void(void)> > {
250  public:
251   typedef Callback<void(void)> CallbackType;
252
253   CallbackList() {}
254
255   void Notify() {
256     cef_internal::CallbackListBase<CallbackType>::Iterator it =
257         this->GetIterator();
258     CallbackType* cb;
259     while ((cb = it.GetNext()) != NULL) {
260       cb->Run();
261     }
262   }
263
264  private:
265   DISALLOW_COPY_AND_ASSIGN(CallbackList);
266 };
267
268 template <typename A1>
269 class CallbackList<void(A1)>
270     : public cef_internal::CallbackListBase<Callback<void(A1)> > {
271  public:
272   typedef Callback<void(A1)> CallbackType;
273
274   CallbackList() {}
275
276   void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) {
277     typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
278         this->GetIterator();
279     CallbackType* cb;
280     while ((cb = it.GetNext()) != NULL) {
281       cb->Run(a1);
282     }
283   }
284
285  private:
286   DISALLOW_COPY_AND_ASSIGN(CallbackList);
287 };
288
289 template <typename A1, typename A2>
290 class CallbackList<void(A1, A2)>
291     : public cef_internal::CallbackListBase<Callback<void(A1, A2)> > {
292  public:
293   typedef Callback<void(A1, A2)> CallbackType;
294
295   CallbackList() {}
296
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 =
300         this->GetIterator();
301     CallbackType* cb;
302     while ((cb = it.GetNext()) != NULL) {
303       cb->Run(a1, a2);
304     }
305   }
306
307  private:
308   DISALLOW_COPY_AND_ASSIGN(CallbackList);
309 };
310
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)> > {
314  public:
315   typedef Callback<void(A1, A2, A3)> CallbackType;
316
317   CallbackList() {}
318
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 =
323         this->GetIterator();
324     CallbackType* cb;
325     while ((cb = it.GetNext()) != NULL) {
326       cb->Run(a1, a2, a3);
327     }
328   }
329
330  private:
331   DISALLOW_COPY_AND_ASSIGN(CallbackList);
332 };
333
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)> > {
337  public:
338   typedef Callback<void(A1, A2, A3, A4)> CallbackType;
339
340   CallbackList() {}
341
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 =
347         this->GetIterator();
348     CallbackType* cb;
349     while ((cb = it.GetNext()) != NULL) {
350       cb->Run(a1, a2, a3, a4);
351     }
352   }
353
354  private:
355   DISALLOW_COPY_AND_ASSIGN(CallbackList);
356 };
357
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)> > {
361  public:
362   typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
363
364   CallbackList() {}
365
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 =
372         this->GetIterator();
373     CallbackType* cb;
374     while ((cb = it.GetNext()) != NULL) {
375       cb->Run(a1, a2, a3, a4, a5);
376     }
377   }
378
379  private:
380   DISALLOW_COPY_AND_ASSIGN(CallbackList);
381 };
382
383 template <typename A1, typename A2, typename A3, typename A4, typename A5,
384     typename A6>
385 class CallbackList<void(A1, A2, A3, A4, A5, A6)>
386     : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5,
387         A6)> > {
388  public:
389   typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
390
391   CallbackList() {}
392
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 =
400         this->GetIterator();
401     CallbackType* cb;
402     while ((cb = it.GetNext()) != NULL) {
403       cb->Run(a1, a2, a3, a4, a5, a6);
404     }
405   }
406
407  private:
408   DISALLOW_COPY_AND_ASSIGN(CallbackList);
409 };
410
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,
415         A7)> > {
416  public:
417   typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
418
419   CallbackList() {}
420
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 =
429         this->GetIterator();
430     CallbackType* cb;
431     while ((cb = it.GetNext()) != NULL) {
432       cb->Run(a1, a2, a3, a4, a5, a6, a7);
433     }
434   }
435
436  private:
437   DISALLOW_COPY_AND_ASSIGN(CallbackList);
438 };
439
440 }  // namespace base
441
442 #endif  // !BUILDING_CEF_SHARED
443
444 #endif  // CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_