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_LIST_H_
16#define BASE_CALLBACK_LIST_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::CallbackList<void(const Foo&)>::Subscription>
43//   RegisterCallback(const OnFooCallback& cb) {
44//     return callback_list_.Add(cb);
45//   }
46//
47//  private:
48//   void NotifyFoo(const Foo& foo) {
49//      callback_list_.Notify(foo);
50//   }
51//
52//   base::CallbackList<void(const Foo&)> callback_list_;
53//
54//   DISALLOW_COPY_AND_ASSIGN(MyWidget);
55// };
56//
57//
58// class MyWidgetListener {
59//  public:
60//   MyWidgetListener::MyWidgetListener() {
61//     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
62//             base::Bind(&MyWidgetListener::OnFoo, this)));
63//   }
64//
65//   MyWidgetListener::~MyWidgetListener() {
66//      // Subscription gets deleted automatically and will deregister
67//      // the callback in the process.
68//   }
69//
70//  private:
71//   void OnFoo(const Foo& foo) {
72//     // Do something.
73//   }
74//
75//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
76//       foo_subscription_;
77//
78//   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
79// };
80
81namespace base {
82
83namespace internal {
84
85template <typename CallbackType>
86class 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    }
95
96    ~Subscription() {
97      if (list_->active_iterator_count_) {
98        iter_->Reset();
99      } else {
100        list_->callbacks_.erase(iter_);
101        if (!list_->removal_callback_.is_null())
102          list_->removal_callback_.Run();
103      }
104    }
105
106   private:
107    CallbackListBase<CallbackType>* list_;
108    typename std::list<CallbackType>::iterator iter_;
109
110    DISALLOW_COPY_AND_ASSIGN(Subscription);
111  };
112
113  // Add a callback to the list. The callback will remain registered until the
114  // returned Subscription is destroyed, which must occur before the
115  // CallbackList is destroyed.
116  scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
117    DCHECK(!cb.is_null());
118    return scoped_ptr<Subscription>(
119        new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
120  }
121
122  // Sets a callback which will be run when a subscription list is changed.
123  void set_removal_callback(const Closure& callback) {
124    removal_callback_ = callback;
125  }
126
127  // Returns true if there are no subscriptions. This is only valid to call when
128  // not looping through the list.
129  bool empty() {
130    DCHECK_EQ(0, active_iterator_count_);
131    return callbacks_.empty();
132  }
133
134 protected:
135  // An iterator class that can be used to access the list of callbacks.
136  class Iterator {
137   public:
138    explicit Iterator(CallbackListBase<CallbackType>* list)
139        : list_(list),
140          list_iter_(list_->callbacks_.begin()) {
141      ++list_->active_iterator_count_;
142    }
143
144    Iterator(const Iterator& iter)
145        : list_(iter.list_),
146          list_iter_(iter.list_iter_) {
147      ++list_->active_iterator_count_;
148    }
149
150    ~Iterator() {
151      if (list_ && --list_->active_iterator_count_ == 0) {
152        list_->Compact();
153      }
154    }
155
156    CallbackType* GetNext() {
157      while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
158        ++list_iter_;
159
160      CallbackType* cb = NULL;
161      if (list_iter_ != list_->callbacks_.end()) {
162        cb = &(*list_iter_);
163        ++list_iter_;
164      }
165      return cb;
166    }
167
168   private:
169    CallbackListBase<CallbackType>* list_;
170    typename std::list<CallbackType>::iterator list_iter_;
171  };
172
173  CallbackListBase() : active_iterator_count_(0) {}
174
175  ~CallbackListBase() {
176    DCHECK_EQ(0, active_iterator_count_);
177    DCHECK_EQ(0U, callbacks_.size());
178  }
179
180  // Returns an instance of a CallbackListBase::Iterator which can be used
181  // to run callbacks.
182  Iterator GetIterator() {
183    return Iterator(this);
184  }
185
186  // Compact the list: remove any entries which were NULLed out during
187  // iteration.
188  void Compact() {
189    typename std::list<CallbackType>::iterator it = callbacks_.begin();
190    bool updated = false;
191    while (it != callbacks_.end()) {
192      if ((*it).is_null()) {
193        updated = true;
194        it = callbacks_.erase(it);
195      } else {
196        ++it;
197      }
198
199      if (updated && !removal_callback_.is_null())
200        removal_callback_.Run();
201    }
202  }
203
204 private:
205  std::list<CallbackType> callbacks_;
206  int active_iterator_count_;
207  Closure removal_callback_;
208
209  DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
210};
211
212}  // namespace internal
213
214template <typename Sig> class CallbackList;
215
216
217$range ARITY 0..MAX_ARITY
218$for ARITY [[
219$range ARG 1..ARITY
220
221$if ARITY == 0 [[
222template <>
223class CallbackList<void(void)>
224    : public internal::CallbackListBase<Callback<void(void)> > {
225]] $else [[
226template <$for ARG , [[typename A$(ARG)]]>
227class CallbackList<void($for ARG , [[A$(ARG)]])>
228    : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > {
229]]
230
231 public:
232$if ARITY == 0 [[
233
234  typedef Callback<void(void)> CallbackType;
235]] $else [[
236
237  typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType;
238]]
239
240
241  CallbackList() {}
242
243  void Notify($for ARG ,
244              [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
245$if ARITY == 0 [[
246
247    internal::CallbackListBase<CallbackType>::Iterator it =
248        this->GetIterator();
249]] $else [[
250
251    typename internal::CallbackListBase<CallbackType>::Iterator it =
252        this->GetIterator();
253]]
254
255    CallbackType* cb;
256    while ((cb = it.GetNext()) != NULL) {
257      cb->Run($for ARG , [[a$(ARG)]]);
258    }
259  }
260
261 private:
262  DISALLOW_COPY_AND_ASSIGN(CallbackList);
263};
264
265
266]]  $$ for ARITY
267}  // namespace base
268
269#endif  // BASE_CALLBACK_LIST_H_
270