Fix race in WebRTC logging.
[chromium-blink-merge.git] / base / callback_list.h.pump
blobea2103ebeefba2ad1567659c8d60deb99f8af9a6
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 $$
8 $$ See comment for MAX_ARITY in base/bind.h.pump.
9 $var MAX_ARITY = 7
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.
15 #ifndef BASE_CALLBACK_LIST_H_
16 #define BASE_CALLBACK_LIST_H_
18 #include <list>
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"
27 // OVERVIEW:
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.
34 // TYPICAL USAGE:
36 // class MyWidget {
37 //  public:
38 //   ...
40 //   typedef base::Callback<void(const Foo&)> OnFooCallback;
42 //   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
43 //   RegisterCallback(const OnFooCallback& cb) {
44 //     return callback_list_.Add(cb);
45 //   }
47 //  private:
48 //   void NotifyFoo(const Foo& foo) {
49 //      callback_list_.Notify(foo);
50 //   }
52 //   base::CallbackList<void(const Foo&)> callback_list_;
54 //   DISALLOW_COPY_AND_ASSIGN(MyWidget);
55 // };
58 // class MyWidgetListener {
59 //  public:
60 //   MyWidgetListener::MyWidgetListener() {
61 //     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
62 //             base::Bind(&MyWidgetListener::OnFoo, this)));
63 //   }
65 //   MyWidgetListener::~MyWidgetListener() {
66 //      // Subscription gets deleted automatically and will deregister
67 //      // the callback in the process.
68 //   }
70 //  private:
71 //   void OnFoo(const Foo& foo) {
72 //     // Do something.
73 //   }
75 //   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
76 //       foo_subscription_;
78 //   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
79 // };
81 namespace base {
83 namespace internal {
85 template <typename CallbackType>
86 class CallbackListBase {
87  public:
88   class Subscription {
89    public:
90     Subscription(CallbackListBase<CallbackType>* list,
91                  typename std::list<CallbackType>::iterator iter)
92         : list_(list),
93           iter_(iter) {
94     }
96     ~Subscription() {
97       if (list_->active_iterator_count_)
98         iter_->Reset();
99       else
100         list_->callbacks_.erase(iter_);
101     }
103    private:
104     CallbackListBase<CallbackType>* list_;
105     typename std::list<CallbackType>::iterator iter_;
107     DISALLOW_COPY_AND_ASSIGN(Subscription);
108   };
110   // Add a callback to the list. The callback will remain registered until the
111   // returned Subscription is destroyed, which must occur before the
112   // CallbackList is destroyed.
113   scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
114     DCHECK(!cb.is_null());
115     return scoped_ptr<Subscription>(
116         new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
117   }
119  protected:
120   // An iterator class that can be used to access the list of callbacks.
121   class Iterator {
122    public:
123     explicit Iterator(CallbackListBase<CallbackType>* list)
124         : list_(list),
125           list_iter_(list_->callbacks_.begin()) {
126       ++list_->active_iterator_count_;
127     }
129     Iterator(const Iterator& iter)
130         : list_(iter.list_),
131           list_iter_(iter.list_iter_) {
132       ++list_->active_iterator_count_;
133     }
135     ~Iterator() {
136       if (list_ && --list_->active_iterator_count_ == 0) {
137         list_->Compact();
138       }
139     }
141     CallbackType* GetNext() {
142       while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
143         ++list_iter_;
145       CallbackType* cb = NULL;
146       if (list_iter_ != list_->callbacks_.end()) {
147         cb = &(*list_iter_);
148         ++list_iter_;
149       }
150       return cb;
151     }
153    private:
154     CallbackListBase<CallbackType>* list_;
155     typename std::list<CallbackType>::iterator list_iter_;
156   };
158   CallbackListBase() : active_iterator_count_(0) {}
160   ~CallbackListBase() {
161     DCHECK_EQ(0, active_iterator_count_);
162     DCHECK_EQ(0U, callbacks_.size());
163   }
165   // Returns an instance of a CallbackListBase::Iterator which can be used
166   // to run callbacks.
167   Iterator GetIterator() {
168     return Iterator(this);
169   }
171   // Compact the list: remove any entries which were NULLed out during
172   // iteration.
173   void Compact() {
174     typename std::list<CallbackType>::iterator it = callbacks_.begin();
175     while (it != callbacks_.end()) {
176       if ((*it).is_null())
177         it = callbacks_.erase(it);
178       else
179         ++it;
180     }
181   }
183  private:
184   std::list<CallbackType> callbacks_;
185   int active_iterator_count_;
187   DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
190 }  // namespace internal
192 template <typename Sig> class CallbackList;
195 $range ARITY 0..MAX_ARITY
196 $for ARITY [[
197 $range ARG 1..ARITY
199 $if ARITY == 0 [[
200 template <>
201 class CallbackList<void(void)>
202     : public internal::CallbackListBase<Callback<void(void)> > {
203 ]] $else [[
204 template <$for ARG , [[typename A$(ARG)]]>
205 class CallbackList<void($for ARG , [[A$(ARG)]])>
206     : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > {
209  public:
210 $if ARITY == 0 [[
212   typedef Callback<void(void)> CallbackType;
213 ]] $else [[
215   typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType;
219   CallbackList() {}
221   void Notify($for ARG ,
222               [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
223 $if ARITY == 0 [[
225     internal::CallbackListBase<CallbackType>::Iterator it =
226         this->GetIterator();
227 ]] $else [[
229     typename internal::CallbackListBase<CallbackType>::Iterator it =
230         this->GetIterator();
233     CallbackType* cb;
234     while ((cb = it.GetNext()) != NULL) {
235       cb->Run($for ARG , [[a$(ARG)]]);
236     }
237   }
239  private:
240   DISALLOW_COPY_AND_ASSIGN(CallbackList);
244 ]]  $$ for ARITY
245 }  // namespace base
247 #endif  // BASE_CALLBACK_LIST_H_