Chromium Code Reviews| Index: base/callback_list_internal.cc |
| diff --git a/base/callback_list_internal.cc b/base/callback_list_internal.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..467d5b992ed2ccc01534e6ff75c68621aa443723 |
| --- /dev/null |
| +++ b/base/callback_list_internal.cc |
| @@ -0,0 +1,109 @@ |
| +// Copyright 2013 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. |
| + |
| +#include "base/callback_list_internal.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| + |
| +namespace base { |
| +namespace internal { |
| + |
| +CallbackListImpl::Iterator::Iterator( |
| + const base::WeakPtr<CallbackListImpl>& list) |
| + : list_(list), |
| + index_(0) { |
| + ++list_->active_iterator_count_; |
| +} |
| + |
| +CallbackListImpl::Iterator::Iterator(const Iterator& iter) |
| + : list_(iter.list_), |
| + index_(iter.index_) { |
| + ++list_->active_iterator_count_; |
| +} |
| + |
| +CallbackListImpl::Iterator::~Iterator() { |
| + if (list_ && --list_->active_iterator_count_ == 0) { |
| + list_->Compact(); |
| + } |
| +} |
| + |
| +CallbackBase* CallbackListImpl::Iterator::GetNext() { |
| + if (!list_) |
| + return NULL; |
| + size_t max_index = list_->callbacks_.size(); |
| + while (index_ < max_index && !list_->callbacks_[index_]) |
| + ++index_; |
| + return index_ < max_index ? list_->callbacks_[index_++] : NULL; |
| +} |
| + |
| +// static |
| +void CallbackListImpl::CheckedRemove( |
| + const base::WeakPtr<CallbackListImpl>& list, |
| + base::internal::CallbackBase* cb) { |
| + list->Remove(cb); |
| +} |
| + |
| +CallbackListImpl::CallbackListImpl() |
| + : active_iterator_count_(0), |
| + weak_factory_(this) {} |
| + |
| +CallbackListImpl::~CallbackListImpl() { |
| + Clear(); |
| +} |
| + |
| +void CallbackListImpl::Clear() { |
| + if (active_iterator_count_) { |
| + for (size_t i = 0; i < callbacks_.size(); ++i) { |
| + CallbackBase* tmp = callbacks_[i]; |
| + delete tmp; |
| + callbacks_[i] = NULL; |
| + } |
| + } else { |
| + for (size_t i = 0; i < callbacks_.size(); ++i) |
| + delete callbacks_[i]; |
| + callbacks_.clear(); |
| + } |
| +} |
| + |
| +void CallbackListImpl::AssertEmpty() { |
| + DCHECK(active_iterator_count_ == 0 && callbacks_.size() == 0); |
|
awong
2013/09/05 22:34:58
This should be a CHECK(). In production, if this i
|
| +} |
| + |
| +void CallbackListImpl::Remove(base::internal::CallbackBase* cb) { |
| + for (size_t i = 0; i < callbacks_.size(); i++) { |
| + if (callbacks_[i] == cb) { |
| + CallbackBase* tmp = callbacks_[i]; |
| + delete tmp; |
| + if (active_iterator_count_) { |
| + callbacks_[i] = NULL; |
| + } else { |
| + callbacks_.erase(callbacks_.begin() + i); |
| + } |
| + return; |
| + } |
| + } |
| +} |
| + |
| +base::Closure CallbackListImpl::Add(base::internal::CallbackBase* cb) { |
| + callbacks_.push_back(cb); |
| + return base::Bind(&CallbackListImpl::CheckedRemove, |
| + weak_factory_.GetWeakPtr(), cb); |
| +} |
| + |
| +CallbackListImpl::Iterator CallbackListImpl::GetIterator() { |
| + return Iterator(weak_factory_.GetWeakPtr()); |
| +} |
| + |
| +void CallbackListImpl::Compact() { |
| + callbacks_.erase( |
| + std::remove(callbacks_.begin(), callbacks_.end(), |
| + static_cast<base::internal::CallbackBase*>(NULL)), |
| + callbacks_.end()); |
| +} |
| + |
| +} // namespace internal |
| +} // namespace base |