LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - observer_list.h (source / functions) Found Hit Coverage
Test: app.info Lines: 37 24 64.9 %
Date: 2012-06-02 Functions: 33 7 21.2 %

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

Generated by: LCOV version 1.7