| Index: cc/scheduler/begin_frame_observer_map.h
|
| diff --git a/cc/scheduler/begin_frame_observer_map.h b/cc/scheduler/begin_frame_observer_map.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..006403074b6b4003e4938d0c9ed08001d1ef2f11
|
| --- /dev/null
|
| +++ b/cc/scheduler/begin_frame_observer_map.h
|
| @@ -0,0 +1,157 @@
|
| +// Copyright 2014 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.
|
| +
|
| +#ifndef CC_SCHEDULER_BEGIN_FRAME_OBSERVER_MAP_H_
|
| +#define CC_SCHEDULER_BEGIN_FRAME_OBSERVER_MAP_H_
|
| +
|
| +#include "base/containers/hash_tables.h"
|
| +#include "base/logging.h"
|
| +
|
| +namespace cc {
|
| +
|
| +template <class ObserverType, class ObserverDataType>
|
| +class BeginFrameObserverMap {
|
| + private:
|
| + typedef typename base::hash_set<ObserverType*> SetType;
|
| + typedef typename base::hash_map<ObserverType*, ObserverDataType*> MapType;
|
| +
|
| + MapType observers_;
|
| +
|
| + volatile size_t const_iterators_;
|
| + size_t iterators_;
|
| + MapType observers_to_add_;
|
| + SetType observers_to_remove_;
|
| +
|
| + public:
|
| + BeginFrameObserverMap()
|
| + : observers_(),
|
| + const_iterators_(0),
|
| + iterators_(0),
|
| + observers_to_add_(),
|
| + observers_to_remove_() {}
|
| +
|
| + class iterator : public MapType::iterator {
|
| + public:
|
| + explicit iterator(
|
| + typename MapType::iterator it,
|
| + BeginFrameObserverMap<ObserverType, ObserverDataType>* list)
|
| + : MapType::iterator(it), list_(list) {
|
| + list_->iterators_++;
|
| + }
|
| + ~iterator() {
|
| + DCHECK_GT(list_->iterators_, 0U);
|
| + list_->iterators_--;
|
| + list_->CompactMaps();
|
| + }
|
| +
|
| + private:
|
| + BeginFrameObserverMap<ObserverType, ObserverDataType>* list_;
|
| + };
|
| +
|
| + class const_iterator : public MapType::const_iterator {
|
| + public:
|
| + explicit const_iterator(
|
| + typename MapType::const_iterator it,
|
| + const BeginFrameObserverMap<ObserverType, ObserverDataType>* list)
|
| + : MapType::const_iterator(it),
|
| + list_(const_cast<
|
| + BeginFrameObserverMap<ObserverType, ObserverDataType>*>(list)) {
|
| + list_->const_iterators_++;
|
| + }
|
| + ~const_iterator() {
|
| + DCHECK_GT(list_->const_iterators_, 0U);
|
| + list_->const_iterators_--;
|
| + }
|
| +
|
| + private:
|
| + BeginFrameObserverMap<ObserverType, ObserverDataType>* list_;
|
| + };
|
| +
|
| + void AddObserver(ObserverType* obs) {
|
| + DCHECK_EQ(const_iterators_, 0U);
|
| + if (observers_to_add_.count(obs) == 0) {
|
| + observers_to_add_[obs] = new ObserverDataType();
|
| + }
|
| + CompactMaps();
|
| + }
|
| +
|
| + void RemoveObserver(ObserverType* obs) {
|
| + DCHECK_EQ(const_iterators_, 0U);
|
| + observers_to_remove_.insert(obs);
|
| + CompactMaps();
|
| + }
|
| +
|
| + bool HasObservers() const { return !observers_.empty(); }
|
| + bool HasObserver(ObserverType* const obs) const {
|
| + return (*this)[obs] != nullptr;
|
| + }
|
| +
|
| + iterator begin() { return iterator(observers_.begin(), this); }
|
| + iterator end() { return iterator(observers_.end(), this); }
|
| +
|
| + const_iterator cbegin() const {
|
| + return const_iterator(const_cast<const MapType*>(&observers_)->begin(),
|
| + this);
|
| + }
|
| +
|
| + const_iterator cend() const {
|
| + return const_iterator(const_cast<const MapType*>(&observers_)->end(), this);
|
| + }
|
| +
|
| + const_iterator begin() const { return cbegin(); }
|
| + const_iterator end() const { return cend(); }
|
| +
|
| + ObserverDataType* operator[](ObserverType* const obs) {
|
| + {
|
| + auto it = observers_.find(obs);
|
| + if (it != observers_.end())
|
| + return it->second;
|
| + }
|
| + {
|
| + auto it = observers_to_add_.find(obs);
|
| + if (it != observers_to_add_.end())
|
| + return it->second;
|
| + }
|
| + return nullptr;
|
| + }
|
| + const ObserverDataType* operator[](ObserverType* const obs) const {
|
| + {
|
| + auto it = observers_.find(obs);
|
| + if (it != observers_.end())
|
| + return it->second;
|
| + }
|
| + {
|
| + auto it = observers_to_add_.find(obs);
|
| + if (it != observers_to_add_.end())
|
| + return it->second;
|
| + }
|
| + return nullptr;
|
| + }
|
| +
|
| + private:
|
| + void CompactMaps() {
|
| + if (iterators_ != 0)
|
| + return;
|
| +
|
| + for (auto it = observers_to_remove_.begin();
|
| + it != observers_to_remove_.end(); it++) {
|
| + delete observers_[*it];
|
| + observers_[*it] = nullptr;
|
| + observers_.erase(*it);
|
| + }
|
| + observers_to_remove_.clear();
|
| +
|
| + for (auto it = observers_to_add_.begin(); it != observers_to_add_.end();
|
| + it++) {
|
| + observers_[it->first] = it->second;
|
| + }
|
| + observers_to_add_.clear();
|
| + }
|
| +
|
| + friend class BeginFrameObserverMapTest;
|
| +};
|
| +
|
| +} // namespace cc
|
| +
|
| +#endif // CC_SCHEDULER_BEGIN_FRAME_OBSERVER_MAP_H_
|
|
|