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