• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    }
102
103   private:
104    CallbackListBase<CallbackType>* list_;
105    typename std::list<CallbackType>::iterator iter_;
106
107    DISALLOW_COPY_AND_ASSIGN(Subscription);
108  };
109
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  }
118
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    }
128
129    Iterator(const Iterator& iter)
130        : list_(iter.list_),
131          list_iter_(iter.list_iter_) {
132      ++list_->active_iterator_count_;
133    }
134
135    ~Iterator() {
136      if (list_ && --list_->active_iterator_count_ == 0) {
137        list_->Compact();
138      }
139    }
140
141    CallbackType* GetNext() {
142      while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
143        ++list_iter_;
144
145      CallbackType* cb = NULL;
146      if (list_iter_ != list_->callbacks_.end()) {
147        cb = &(*list_iter_);
148        ++list_iter_;
149      }
150      return cb;
151    }
152
153   private:
154    CallbackListBase<CallbackType>* list_;
155    typename std::list<CallbackType>::iterator list_iter_;
156  };
157
158  CallbackListBase() : active_iterator_count_(0) {}
159
160  ~CallbackListBase() {
161    DCHECK_EQ(0, active_iterator_count_);
162    DCHECK_EQ(0U, callbacks_.size());
163  }
164
165  // Returns an instance of a CallbackListBase::Iterator which can be used
166  // to run callbacks.
167  Iterator GetIterator() {
168    return Iterator(this);
169  }
170
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  }
182
183 private:
184  std::list<CallbackType> callbacks_;
185  int active_iterator_count_;
186
187  DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
188};
189
190}  // namespace internal
191
192template <typename Sig> class CallbackList;
193
194
195$range ARITY 0..MAX_ARITY
196$for ARITY [[
197$range ARG 1..ARITY
198
199$if ARITY == 0 [[
200template <>
201class CallbackList<void(void)>
202    : public internal::CallbackListBase<Callback<void(void)> > {
203]] $else [[
204template <$for ARG , [[typename A$(ARG)]]>
205class CallbackList<void($for ARG , [[A$(ARG)]])>
206    : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > {
207]]
208
209 public:
210$if ARITY == 0 [[
211
212  typedef Callback<void(void)> CallbackType;
213]] $else [[
214
215  typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType;
216]]
217
218
219  CallbackList() {}
220
221  void Notify($for ARG ,
222              [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
223$if ARITY == 0 [[
224
225    internal::CallbackListBase<CallbackType>::Iterator it =
226        this->GetIterator();
227]] $else [[
228
229    typename internal::CallbackListBase<CallbackType>::Iterator it =
230        this->GetIterator();
231]]
232
233    CallbackType* cb;
234    while ((cb = it.GetNext()) != NULL) {
235      cb->Run($for ARG , [[a$(ARG)]]);
236    }
237  }
238
239 private:
240  DISALLOW_COPY_AND_ASSIGN(CallbackList);
241};
242
243
244]]  $$ for ARITY
245}  // namespace base
246
247#endif  // BASE_CALLBACK_LIST_H_
248