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..76f7b1cb21e1c6bd7e68b58d4962543ad3b96d7a |
--- /dev/null |
+++ b/base/callback_list_internal.cc |
@@ -0,0 +1,91 @@ |
+// 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() { |
+ 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; |
+} |
+ |
+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::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::Remove, Unretained(this), cb); |
+} |
+ |
+scoped_ptr<CallbackListImpl::Iterator> CallbackListImpl::GetIterator() { |
+ return make_scoped_ptr(new 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 |