1// This file was GENERATED by command:
2//     pump.py callback_list.h.pump
3// DO NOT EDIT BY HAND!!!
4
5
6// Copyright 2013 The Chromium Authors. All rights reserved.
7// Use of this source code is governed by a BSD-style license that can be
8// found in the LICENSE file.
9
10#ifndef BASE_CALLBACK_LIST_H_
11#define BASE_CALLBACK_LIST_H_
12
13#include <list>
14
15#include "base/basictypes.h"
16#include "base/callback.h"
17#include "base/callback_internal.h"
18#include "base/compiler_specific.h"
19#include "base/logging.h"
20#include "base/memory/scoped_ptr.h"
21
22// OVERVIEW:
23//
24// A container for a list of callbacks.  Unlike a normal STL vector or list,
25// this container can be modified during iteration without invalidating the
26// iterator. It safely handles the case of a callback removing itself
27// or another callback from the list while callbacks are being run.
28//
29// TYPICAL USAGE:
30//
31// class MyWidget {
32//  public:
33//   ...
34//
35//   typedef base::Callback<void(const Foo&)> OnFooCallback;
36//
37//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
38//   RegisterCallback(const OnFooCallback& cb) {
39//     return callback_list_.Add(cb);
40//   }
41//
42//  private:
43//   void NotifyFoo(const Foo& foo) {
44//      callback_list_.Notify(foo);
45//   }
46//
47//   base::CallbackList<void(const Foo&)> callback_list_;
48//
49//   DISALLOW_COPY_AND_ASSIGN(MyWidget);
50// };
51//
52//
53// class MyWidgetListener {
54//  public:
55//   MyWidgetListener::MyWidgetListener() {
56//     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
57//             base::Bind(&MyWidgetListener::OnFoo, this)));
58//   }
59//
60//   MyWidgetListener::~MyWidgetListener() {
61//      // Subscription gets deleted automatically and will deregister
62//      // the callback in the process.
63//   }
64//
65//  private:
66//   void OnFoo(const Foo& foo) {
67//     // Do something.
68//   }
69//
70//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
71//       foo_subscription_;
72//
73//   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
74// };
75
76namespace base {
77
78namespace internal {
79
80template <typename CallbackType>
81class CallbackListBase {
82 public:
83  class Subscription {
84   public:
85    Subscription(CallbackListBase<CallbackType>* list,
86                 typename std::list<CallbackType>::iterator iter)
87        : list_(list),
88          iter_(iter) {
89    }
90
91    ~Subscription() {
92      if (list_->active_iterator_count_) {
93        iter_->Reset();
94      } else {
95        list_->callbacks_.erase(iter_);
96        if (!list_->removal_callback_.is_null())
97          list_->removal_callback_.Run();
98      }
99    }
100
101   private:
102    CallbackListBase<CallbackType>* list_;
103    typename std::list<CallbackType>::iterator iter_;
104
105    DISALLOW_COPY_AND_ASSIGN(Subscription);
106  };
107
108  // Add a callback to the list. The callback will remain registered until the
109  // returned Subscription is destroyed, which must occur before the
110  // CallbackList is destroyed.
111  scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
112    DCHECK(!cb.is_null());
113    return scoped_ptr<Subscription>(
114        new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
115  }
116
117  // Sets a callback which will be run when a subscription list is changed.
118  void set_removal_callback(const Closure& callback) {
119    removal_callback_ = callback;
120  }
121
122  // Returns true if there are no subscriptions. This is only valid to call when
123  // not looping through the list.
124  bool empty() {
125    DCHECK_EQ(0, active_iterator_count_);
126    return callbacks_.empty();
127  }
128
129 protected:
130  // An iterator class that can be used to access the list of callbacks.
131  class Iterator {
132   public:
133    explicit Iterator(CallbackListBase<CallbackType>* list)
134        : list_(list),
135          list_iter_(list_->callbacks_.begin()) {
136      ++list_->active_iterator_count_;
137    }
138
139    Iterator(const Iterator& iter)
140        : list_(iter.list_),
141          list_iter_(iter.list_iter_) {
142      ++list_->active_iterator_count_;
143    }
144
145    ~Iterator() {
146      if (list_ && --list_->active_iterator_count_ == 0) {
147        list_->Compact();
148      }
149    }
150
151    CallbackType* GetNext() {
152      while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
153        ++list_iter_;
154
155      CallbackType* cb = NULL;
156      if (list_iter_ != list_->callbacks_.end()) {
157        cb = &(*list_iter_);
158        ++list_iter_;
159      }
160      return cb;
161    }
162
163   private:
164    CallbackListBase<CallbackType>* list_;
165    typename std::list<CallbackType>::iterator list_iter_;
166  };
167
168  CallbackListBase() : active_iterator_count_(0) {}
169
170  ~CallbackListBase() {
171    DCHECK_EQ(0, active_iterator_count_);
172    DCHECK_EQ(0U, callbacks_.size());
173  }
174
175  // Returns an instance of a CallbackListBase::Iterator which can be used
176  // to run callbacks.
177  Iterator GetIterator() {
178    return Iterator(this);
179  }
180
181  // Compact the list: remove any entries which were NULLed out during
182  // iteration.
183  void Compact() {
184    typename std::list<CallbackType>::iterator it = callbacks_.begin();
185    bool updated = false;
186    while (it != callbacks_.end()) {
187      if ((*it).is_null()) {
188        updated = true;
189        it = callbacks_.erase(it);
190      } else {
191        ++it;
192      }
193
194      if (updated && !removal_callback_.is_null())
195        removal_callback_.Run();
196    }
197  }
198
199 private:
200  std::list<CallbackType> callbacks_;
201  int active_iterator_count_;
202  Closure removal_callback_;
203
204  DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
205};
206
207}  // namespace internal
208
209template <typename Sig> class CallbackList;
210
211template <>
212class CallbackList<void(void)>
213    : public internal::CallbackListBase<Callback<void(void)> > {
214 public:
215  typedef Callback<void(void)> CallbackType;
216
217  CallbackList() {}
218
219  void Notify() {
220    internal::CallbackListBase<CallbackType>::Iterator it =
221        this->GetIterator();
222    CallbackType* cb;
223    while ((cb = it.GetNext()) != NULL) {
224      cb->Run();
225    }
226  }
227
228 private:
229  DISALLOW_COPY_AND_ASSIGN(CallbackList);
230};
231
232template <typename A1>
233class CallbackList<void(A1)>
234    : public internal::CallbackListBase<Callback<void(A1)> > {
235 public:
236  typedef Callback<void(A1)> CallbackType;
237
238  CallbackList() {}
239
240  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1) {
241    typename internal::CallbackListBase<CallbackType>::Iterator it =
242        this->GetIterator();
243    CallbackType* cb;
244    while ((cb = it.GetNext()) != NULL) {
245      cb->Run(a1);
246    }
247  }
248
249 private:
250  DISALLOW_COPY_AND_ASSIGN(CallbackList);
251};
252
253template <typename A1, typename A2>
254class CallbackList<void(A1, A2)>
255    : public internal::CallbackListBase<Callback<void(A1, A2)> > {
256 public:
257  typedef Callback<void(A1, A2)> CallbackType;
258
259  CallbackList() {}
260
261  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
262              typename internal::CallbackParamTraits<A2>::ForwardType a2) {
263    typename internal::CallbackListBase<CallbackType>::Iterator it =
264        this->GetIterator();
265    CallbackType* cb;
266    while ((cb = it.GetNext()) != NULL) {
267      cb->Run(a1, a2);
268    }
269  }
270
271 private:
272  DISALLOW_COPY_AND_ASSIGN(CallbackList);
273};
274
275template <typename A1, typename A2, typename A3>
276class CallbackList<void(A1, A2, A3)>
277    : public internal::CallbackListBase<Callback<void(A1, A2, A3)> > {
278 public:
279  typedef Callback<void(A1, A2, A3)> CallbackType;
280
281  CallbackList() {}
282
283  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
284              typename internal::CallbackParamTraits<A2>::ForwardType a2,
285              typename internal::CallbackParamTraits<A3>::ForwardType a3) {
286    typename internal::CallbackListBase<CallbackType>::Iterator it =
287        this->GetIterator();
288    CallbackType* cb;
289    while ((cb = it.GetNext()) != NULL) {
290      cb->Run(a1, a2, a3);
291    }
292  }
293
294 private:
295  DISALLOW_COPY_AND_ASSIGN(CallbackList);
296};
297
298template <typename A1, typename A2, typename A3, typename A4>
299class CallbackList<void(A1, A2, A3, A4)>
300    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4)> > {
301 public:
302  typedef Callback<void(A1, A2, A3, A4)> CallbackType;
303
304  CallbackList() {}
305
306  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
307              typename internal::CallbackParamTraits<A2>::ForwardType a2,
308              typename internal::CallbackParamTraits<A3>::ForwardType a3,
309              typename internal::CallbackParamTraits<A4>::ForwardType a4) {
310    typename internal::CallbackListBase<CallbackType>::Iterator it =
311        this->GetIterator();
312    CallbackType* cb;
313    while ((cb = it.GetNext()) != NULL) {
314      cb->Run(a1, a2, a3, a4);
315    }
316  }
317
318 private:
319  DISALLOW_COPY_AND_ASSIGN(CallbackList);
320};
321
322template <typename A1, typename A2, typename A3, typename A4, typename A5>
323class CallbackList<void(A1, A2, A3, A4, A5)>
324    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5)> > {
325 public:
326  typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
327
328  CallbackList() {}
329
330  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
331              typename internal::CallbackParamTraits<A2>::ForwardType a2,
332              typename internal::CallbackParamTraits<A3>::ForwardType a3,
333              typename internal::CallbackParamTraits<A4>::ForwardType a4,
334              typename internal::CallbackParamTraits<A5>::ForwardType a5) {
335    typename internal::CallbackListBase<CallbackType>::Iterator it =
336        this->GetIterator();
337    CallbackType* cb;
338    while ((cb = it.GetNext()) != NULL) {
339      cb->Run(a1, a2, a3, a4, a5);
340    }
341  }
342
343 private:
344  DISALLOW_COPY_AND_ASSIGN(CallbackList);
345};
346
347template <typename A1, typename A2, typename A3, typename A4, typename A5,
348    typename A6>
349class CallbackList<void(A1, A2, A3, A4, A5, A6)>
350    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5,
351        A6)> > {
352 public:
353  typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
354
355  CallbackList() {}
356
357  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
358              typename internal::CallbackParamTraits<A2>::ForwardType a2,
359              typename internal::CallbackParamTraits<A3>::ForwardType a3,
360              typename internal::CallbackParamTraits<A4>::ForwardType a4,
361              typename internal::CallbackParamTraits<A5>::ForwardType a5,
362              typename internal::CallbackParamTraits<A6>::ForwardType a6) {
363    typename internal::CallbackListBase<CallbackType>::Iterator it =
364        this->GetIterator();
365    CallbackType* cb;
366    while ((cb = it.GetNext()) != NULL) {
367      cb->Run(a1, a2, a3, a4, a5, a6);
368    }
369  }
370
371 private:
372  DISALLOW_COPY_AND_ASSIGN(CallbackList);
373};
374
375template <typename A1, typename A2, typename A3, typename A4, typename A5,
376    typename A6, typename A7>
377class CallbackList<void(A1, A2, A3, A4, A5, A6, A7)>
378    : public internal::CallbackListBase<Callback<void(A1, A2, A3, A4, A5, A6,
379        A7)> > {
380 public:
381  typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
382
383  CallbackList() {}
384
385  void Notify(typename internal::CallbackParamTraits<A1>::ForwardType a1,
386              typename internal::CallbackParamTraits<A2>::ForwardType a2,
387              typename internal::CallbackParamTraits<A3>::ForwardType a3,
388              typename internal::CallbackParamTraits<A4>::ForwardType a4,
389              typename internal::CallbackParamTraits<A5>::ForwardType a5,
390              typename internal::CallbackParamTraits<A6>::ForwardType a6,
391              typename internal::CallbackParamTraits<A7>::ForwardType a7) {
392    typename internal::CallbackListBase<CallbackType>::Iterator it =
393        this->GetIterator();
394    CallbackType* cb;
395    while ((cb = it.GetNext()) != NULL) {
396      cb->Run(a1, a2, a3, a4, a5, a6, a7);
397    }
398  }
399
400 private:
401  DISALLOW_COPY_AND_ASSIGN(CallbackList);
402};
403
404}  // namespace base
405
406#endif  // BASE_CALLBACK_LIST_H_
407