LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - observer_list.h (source / functions) Hit Total Coverage
Test: output.info Lines: 33 37 89.2 %
Date: 2017-07-14 16:53:18 Functions: 8 16 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #ifndef BASE_OBSERVER_LIST_H__
       8             : #define BASE_OBSERVER_LIST_H__
       9             : 
      10             : #include <algorithm>
      11             : #include <limits>
      12             : #include <vector>
      13             : 
      14             : #include "base/basictypes.h"
      15             : #include "base/logging.h"
      16             : 
      17             : #if defined(ANDROID) && defined(_STLP_STD_NAME)
      18             : using _STLP_STD_NAME::find;
      19             : #endif
      20             : 
      21             : namespace base {
      22             : 
      23             : ///////////////////////////////////////////////////////////////////////////////
      24             : //
      25             : // OVERVIEW:
      26             : //
      27             : //   A container for a list of observers.  Unlike a normal STL vector or list,
      28             : //   this container can be modified during iteration without invalidating the
      29             : //   iterator.  So, it safely handles the case of an observer removing itself
      30             : //   or other observers from the list while observers are being notified.
      31             : //
      32             : // TYPICAL USAGE:
      33             : //
      34             : //   class MyWidget {
      35             : //    public:
      36             : //     ...
      37             : //
      38             : //     class Observer {
      39             : //      public:
      40             : //       virtual void OnFoo(MyWidget* w) = 0;
      41             : //       virtual void OnBar(MyWidget* w, int x, int y) = 0;
      42             : //     };
      43             : //
      44             : //     void AddObserver(Observer* obs) {
      45             : //       observer_list_.AddObserver(obs);
      46             : //     }
      47             : //
      48             : //     void RemoveObserver(Observer* obs) {
      49             : //       observer_list_.RemoveObserver(obs);
      50             : //     }
      51             : //
      52             : //     void NotifyFoo() {
      53             : //       FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
      54             : //     }
      55             : //
      56             : //     void NotifyBar(int x, int y) {
      57             : //       FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
      58             : //     }
      59             : //
      60             : //    private:
      61             : //     ObserverList<Observer> observer_list_;
      62             : //   };
      63             : //
      64             : //
      65             : ///////////////////////////////////////////////////////////////////////////////
      66             : 
      67             : template <class ObserverType, bool check_empty = false>
      68             : class ObserverList {
      69             :  public:
      70             :   // Enumeration of which observers are notified.
      71             :   enum NotificationType {
      72             :     // Specifies that any observers added during notification are notified.
      73             :     // This is the default type if non type is provided to the constructor.
      74             :     NOTIFY_ALL,
      75             : 
      76             :     // Specifies that observers added while sending out notification are not
      77             :     // notified.
      78             :     NOTIFY_EXISTING_ONLY
      79             :   };
      80             : 
      81          67 :   ObserverList() : notify_depth_(0), type_(NOTIFY_ALL) {}
      82             :   explicit ObserverList(NotificationType type) : notify_depth_(0), type_(type) {}
      83           1 :   ~ObserverList() {
      84             :     // When check_empty is true, assert that the list is empty on destruction.
      85             :     if (check_empty) {
      86             :       Compact();
      87             :       DCHECK_EQ(observers_.size(), 0U);
      88             :     }
      89           1 :   }
      90             : 
      91             :   // Add an observer to the list.
      92         105 :   void AddObserver(ObserverType* obs) {
      93         105 :     DCHECK(find(observers_.begin(), observers_.end(), obs) == observers_.end())
      94           0 :         << "Observers can only be added once!";
      95         105 :     observers_.push_back(obs);
      96         105 :   }
      97             : 
      98             :   // Remove an observer from the list.
      99           1 :   void RemoveObserver(ObserverType* obs) {
     100             :     typename ListType::iterator it =
     101           1 :       std::find(observers_.begin(), observers_.end(), obs);
     102           1 :     if (it != observers_.end()) {
     103           1 :       if (notify_depth_) {
     104           1 :         *it = 0;
     105             :       } else {
     106           0 :         observers_.erase(it);
     107             :       }
     108             :     }
     109           1 :   }
     110             : 
     111             :   size_t size() const {
     112             :     return observers_.size();
     113             :   }
     114             : 
     115             :   ObserverType* GetElementAt(int index) const {
     116             :     return observers_[index];
     117             :   }
     118             : 
     119             :   // An iterator class that can be used to access the list of observers.  See
     120             :   // also the FOREACH_OBSERVER macro defined below.
     121             :   class Iterator {
     122             :    public:
     123           1 :     explicit Iterator(const ObserverList<ObserverType>& list)
     124             :         : list_(list),
     125             :           index_(0),
     126           1 :           max_index_(list.type_ == NOTIFY_ALL ?
     127             :                      std::numeric_limits<size_t>::max() :
     128           2 :                      list.observers_.size()) {
     129           1 :       ++list_.notify_depth_;
     130           1 :     }
     131             : 
     132           1 :     ~Iterator() {
     133           1 :       if (--list_.notify_depth_ == 0)
     134           1 :         list_.Compact();
     135           1 :     }
     136             : 
     137           2 :     ObserverType* GetNext() {
     138           2 :       ListType& observers = list_.observers_;
     139             :       // Advance if the current element is null
     140           2 :       size_t max_index = std::min(max_index_, observers.size());
     141           2 :       while (index_ < max_index && !observers[index_])
     142           0 :         ++index_;
     143           2 :       return index_ < max_index ? observers[index_++] : NULL;
     144             :     }
     145             : 
     146             :    private:
     147             :     const ObserverList<ObserverType>& list_;
     148             :     size_t index_;
     149             :     size_t max_index_;
     150             :   };
     151             : 
     152             :  private:
     153             :   typedef std::vector<ObserverType*> ListType;
     154             : 
     155           1 :   void Compact() const {
     156           1 :     typename ListType::iterator it = observers_.begin();
     157           3 :     while (it != observers_.end()) {
     158           1 :       if (*it) {
     159           0 :         ++it;
     160             :       } else {
     161           1 :         it = observers_.erase(it);
     162             :       }
     163             :     }
     164           1 :   }
     165             : 
     166             :   // These are marked mutable to facilitate having NotifyAll be const.
     167             :   mutable ListType observers_;
     168             :   mutable int notify_depth_;
     169             :   NotificationType type_;
     170             : 
     171             :   friend class ObserverList::Iterator;
     172             : 
     173             :   DISALLOW_EVIL_CONSTRUCTORS(ObserverList);
     174             : };
     175             : 
     176             : } // namespace base
     177             : 
     178             : #define FOR_EACH_OBSERVER(ObserverType, observer_list, func)            \
     179             :   do {                                                                  \
     180             :     base::ObserverList<ObserverType>::Iterator it(observer_list); \
     181             :     ObserverType* obs;                                                  \
     182             :     while ((obs = it.GetNext()) != NULL)                                \
     183             :       obs->func;                                                     \
     184             :   } while (0)
     185             : 
     186             : #endif  // BASE_OBSERVER_LIST_H__

Generated by: LCOV version 1.13