Home | History | Annotate | Download | only in shelf
      1 // Copyright 2013 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 ASH_SHELF_SCOPED_OBSERVER_WITH_DUPLICATED_SOURCES_H_
      6 #define ASH_SHELF_SCOPED_OBSERVER_WITH_DUPLICATED_SOURCES_H_
      7 
      8 #include <map>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/logging.h"
     12 
     13 // ScopedObserverWithDuplicatedSources is used to keep track of the set of
     14 // sources an object has attached itself to as an observer. When
     15 // ScopedObserverWithDuplicatedSources is destroyed it removes the object as an
     16 // observer from all sources it has been added to.
     17 // ScopedObserverWithDuplicatedSources adds |observer| once for a particular
     18 // source, no matter how many times Add() is invoked. Additionaly |observer| is
     19 // only removed once Remove() is invoked the same number of times as Add().
     20 
     21 template <class Source, class Observer>
     22 class ScopedObserverWithDuplicatedSources {
     23  public:
     24   explicit ScopedObserverWithDuplicatedSources(Observer* observer)
     25       : observer_(observer) {}
     26 
     27   ~ScopedObserverWithDuplicatedSources() {
     28     typename SourceToAddCountMap::const_iterator iter =
     29         counted_sources_.begin();
     30     for (; iter != counted_sources_.end(); ++iter)
     31       iter->first->RemoveObserver(observer_);
     32   }
     33 
     34   // Adds the object passed to the constructor only once as an observer on
     35   // |source|.
     36   void Add(Source* source) {
     37     if (counted_sources_.find(source) == counted_sources_.end())
     38       source->AddObserver(observer_);
     39     counted_sources_[source]++;
     40   }
     41 
     42   // Only remove the object passed to the constructor as an observer from
     43   // |source| when Remove() is invoked the same number of times as Add().
     44   void Remove(Source* source) {
     45     typename SourceToAddCountMap::iterator iter =
     46         counted_sources_.find(source);
     47     DCHECK(iter != counted_sources_.end() && iter->second > 0);
     48 
     49     if (--iter->second == 0) {
     50       counted_sources_.erase(source);
     51       source->RemoveObserver(observer_);
     52     }
     53   }
     54 
     55   bool IsObserving(Source* source) const {
     56     return counted_sources_.find(source) != counted_sources_.end();
     57   }
     58 
     59  private:
     60   typedef std::map<Source*, int> SourceToAddCountMap;
     61 
     62   Observer* observer_;
     63 
     64   // Map Source and its adding count.
     65   std::map<Source*, int> counted_sources_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(ScopedObserverWithDuplicatedSources);
     68 };
     69 
     70 #endif  // ASH_SHELF_SCOPED_OBSERVER_WITH_DUPLICATED_SOURCES_H_
     71