// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
#ifdefined(ANDROID) && defined(_STLP_STD_NAME) using _STLP_STD_NAME::find; #endif
namespace base {
/////////////////////////////////////////////////////////////////////////////// // // OVERVIEW: // // A container for a list of observers. Unlike a normal STL vector or list, // this container can be modified during iteration without invalidating the // iterator. So, it safely handles the case of an observer removing itself // or other observers from the list while observers are being notified. // // TYPICAL USAGE: // // class MyWidget { // public: // ... // // class Observer { // public: // virtual void OnFoo(MyWidget* w) = 0; // virtual void OnBar(MyWidget* w, int x, int y) = 0; // }; // // void AddObserver(Observer* obs) { // observer_list_.AddObserver(obs); // } // // void RemoveObserver(Observer* obs) { // observer_list_.RemoveObserver(obs); // } // // void NotifyFoo() { // FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this)); // } // // void NotifyBar(int x, int y) { // FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); // } // // private: // ObserverList<Observer> observer_list_; // }; // // ///////////////////////////////////////////////////////////////////////////////
template <class ObserverType, bool check_empty = false> class ObserverList { public: // Enumeration of which observers are notified. enum NotificationType { // Specifies that any observers added during notification are notified. // This is the default type if non type is provided to the constructor.
NOTIFY_ALL,
// Specifies that observers added while sending out notification are not // notified.
NOTIFY_EXISTING_ONLY
};
ObserverList() : notify_depth_(0), type_(NOTIFY_ALL) {} explicit ObserverList(NotificationType type)
: notify_depth_(0), type_(type) {}
~ObserverList() { // When check_empty is true, assert that the list is empty on destruction. if (check_empty) {
Compact();
DCHECK_EQ(observers_.size(), 0U);
}
}
// Add an observer to the list. void AddObserver(ObserverType* obs) {
DCHECK(find(observers_.begin(), observers_.end(), obs) == observers_.end())
<< "Observers can only be added once!";
observers_.push_back(obs);
}
// Remove an observer from the list. void RemoveObserver(ObserverType* obs) { typename ListType::iterator it =
std::find(observers_.begin(), observers_.end(), obs); if (it != observers_.end()) { if (notify_depth_) {
*it = 0;
} else {
observers_.erase(it);
}
}
}
// An iterator class that can be used to access the list of observers. See // also the FOREACH_OBSERVER macro defined below. class Iterator { public: explicit Iterator(const ObserverList<ObserverType>& list)
: list_(list),
index_(0),
max_index_(list.type_ == NOTIFY_ALL
? std::numeric_limits<size_t>::max()
: list.observers_.size()) {
++list_.notify_depth_;
}
~Iterator() { if (--list_.notify_depth_ == 0) list_.Compact();
}
ObserverType* GetNext() {
ListType& observers = list_.observers_; // Advance if the current element is null
size_t max_index = std::min(max_index_, observers.size()); while (index_ < max_index && !observers[index_]) ++index_; return index_ < max_index ? observers[index_++] : NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.