15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_OBSERVER_LIST_H__
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_OBSERVER_LIST_H__
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OVERVIEW:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   A container for a list of observers.  Unlike a normal STL vector or list,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   this container can be modified during iteration without invalidating the
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   iterator.  So, it safely handles the case of an observer removing itself
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   or other observers from the list while observers are being notified.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TYPICAL USAGE:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   class MyWidget {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    public:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     ...
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     class Observer {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      public:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       virtual void OnFoo(MyWidget* w) = 0;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       virtual void OnBar(MyWidget* w, int x, int y) = 0;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     };
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     void AddObserver(Observer* obs) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       observer_list_.AddObserver(obs);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     void RemoveObserver(Observer* obs) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       observer_list_.RemoveObserver(obs);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     void NotifyFoo() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     void NotifyBar(int x, int y) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    private:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     ObserverList<Observer> observer_list_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   };
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename ObserverType>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ObserverListThreadSafe;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class ObserverType>
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ObserverListBase
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::SupportsWeakPtr<ObserverListBase<ObserverType> > {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enumeration of which observers are notified.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum NotificationType {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Specifies that any observers added during notification are notified.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is the default type if non type is provided to the constructor.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIFY_ALL,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Specifies that observers added while sending out notification are not
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // notified.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIFY_EXISTING_ONLY
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An iterator class that can be used to access the list of observers.  See
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // also the FOR_EACH_OBSERVER macro defined below.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Iterator {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Iterator(ObserverListBase<ObserverType>& list);
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ~Iterator();
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ObserverType* GetNext();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<ObserverListBase<ObserverType> > list_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t index_;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_index_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ObserverListBase(NotificationType type)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : notify_depth_(0), type_(type) {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add an observer to the list.  An observer should not be added to
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the same list more than once.
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void AddObserver(ObserverType* obs);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove an observer from the list if it is in the list.
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void RemoveObserver(ObserverType* obs);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool HasObserver(ObserverType* observer) const;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void Clear();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) protected:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const { return observers_.size(); }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void Compact();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class ObserverListThreadSafe<ObserverType>;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<ObserverType*> ListType;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListType observers_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int notify_depth_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationType type_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class ObserverListBase::Iterator;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ObserverListBase);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
127116680a4aac90f2aa7413d9095a592090648e557Ben MurdochObserverListBase<ObserverType>::Iterator::Iterator(
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ObserverListBase<ObserverType>& list)
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : list_(list.AsWeakPtr()),
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      index_(0),
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      max_index_(list.type_ == NOTIFY_ALL ?
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 std::numeric_limits<size_t>::max() :
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 list.observers_.size()) {
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ++list_->notify_depth_;
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
138116680a4aac90f2aa7413d9095a592090648e557Ben MurdochObserverListBase<ObserverType>::Iterator::~Iterator() {
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (list_.get() && --list_->notify_depth_ == 0)
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    list_->Compact();
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
144116680a4aac90f2aa7413d9095a592090648e557Ben MurdochObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() {
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!list_.get())
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ListType& observers = list_->observers_;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Advance if the current element is null
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t max_index = std::min(max_index_, observers.size());
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (index_ < max_index && !observers[index_])
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ++index_;
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return index_ < max_index ? observers[index_++] : NULL;
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) {
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (std::find(observers_.begin(), observers_.end(), obs)
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      != observers_.end()) {
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NOTREACHED() << "Observers can only be added once!";
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observers_.push_back(obs);
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ObserverListBase<ObserverType>::RemoveObserver(ObserverType* obs) {
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typename ListType::iterator it =
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::find(observers_.begin(), observers_.end(), obs);
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (it != observers_.end()) {
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (notify_depth_) {
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *it = 0;
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      observers_.erase(it);
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ObserverListBase<ObserverType>::HasObserver(ObserverType* observer) const {
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < observers_.size(); ++i) {
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (observers_[i] == observer)
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return true;
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ObserverListBase<ObserverType>::Clear() {
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (notify_depth_) {
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (typename ListType::iterator it = observers_.begin();
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      it != observers_.end(); ++it) {
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *it = 0;
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    observers_.clear();
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtemplate <class ObserverType>
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ObserverListBase<ObserverType>::Compact() {
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observers_.erase(
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      std::remove(observers_.begin(), observers_.end(),
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  static_cast<ObserverType*>(NULL)), observers_.end());
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class ObserverType, bool check_empty = false>
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ObserverList : public ObserverListBase<ObserverType> {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef typename ObserverListBase<ObserverType>::NotificationType
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotificationType;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList() {}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ObserverList(NotificationType type)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ObserverListBase<ObserverType>(type) {}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ObserverList() {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When check_empty is true, assert that the list is empty on destruction.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (check_empty) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ObserverListBase<ObserverType>::Compact();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(ObserverListBase<ObserverType>::size(), 0U);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool might_have_observers() const {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ObserverListBase<ObserverType>::size() != 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define FOR_EACH_OBSERVER(ObserverType, observer_list, func)               \
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  do {                                                                     \
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((observer_list).might_have_observers()) {                          \
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ObserverListBase<ObserverType>::Iterator                             \
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          it_inside_observer_macro(observer_list);                         \
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ObserverType* obs;                                                   \
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      while ((obs = it_inside_observer_macro.GetNext()) != NULL)           \
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        obs->func;                                                         \
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }                                                                      \
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (0)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_OBSERVER_LIST_H__
241