aboutsummaryrefslogtreecommitdiff
path: root/third_party/chromium/base/callback_list.h
diff options
context:
space:
mode:
authorPaul Westbrook <pwestbro@google.com>2015-11-01 15:29:33 -0800
committerPaul Westbrook <pwestbro@google.com>2015-11-02 18:55:30 +0000
commit5a1f600e9d7d26c36b3e22ff0dc0ae9e3b2425fc (patch)
tree9a3a96971d8c687c1a1976dc9abf49dd8d3c62f2 /third_party/chromium/base/callback_list.h
parent1bc421c9ef13ad855a3f749143fa8c4bc568ef16 (diff)
downloadlibweave-5a1f600e9d7d26c36b3e22ff0dc0ae9e3b2425fc.tar.gz
Remove the unneeded libweave directory
Change-Id: I30fd8c5626cf83da6415ffa14a2019ef43be9916 Reviewed-on: https://weave-review.googlesource.com/1450 Reviewed-by: Paul Westbrook <pwestbro@google.com>
Diffstat (limited to 'third_party/chromium/base/callback_list.h')
-rw-r--r--third_party/chromium/base/callback_list.h230
1 files changed, 230 insertions, 0 deletions
diff --git a/third_party/chromium/base/callback_list.h b/third_party/chromium/base/callback_list.h
new file mode 100644
index 0000000..aeed5f1
--- /dev/null
+++ b/third_party/chromium/base/callback_list.h
@@ -0,0 +1,230 @@
+// 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.
+
+#ifndef BASE_CALLBACK_LIST_H_
+#define BASE_CALLBACK_LIST_H_
+
+#include <list>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/callback_internal.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+
+// OVERVIEW:
+//
+// A container for a list of callbacks. Unlike a normal STL vector or list,
+// this container can be modified during iteration without invalidating the
+// iterator. It safely handles the case of a callback removing itself
+// or another callback from the list while callbacks are being run.
+//
+// TYPICAL USAGE:
+//
+// class MyWidget {
+// public:
+// ...
+//
+// typedef base::Callback<void(const Foo&)> OnFooCallback;
+//
+// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
+// RegisterCallback(const OnFooCallback& cb) {
+// return callback_list_.Add(cb);
+// }
+//
+// private:
+// void NotifyFoo(const Foo& foo) {
+// callback_list_.Notify(foo);
+// }
+//
+// base::CallbackList<void(const Foo&)> callback_list_;
+//
+// DISALLOW_COPY_AND_ASSIGN(MyWidget);
+// };
+//
+//
+// class MyWidgetListener {
+// public:
+// MyWidgetListener::MyWidgetListener() {
+// foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
+// base::Bind(&MyWidgetListener::OnFoo, this)));
+// }
+//
+// MyWidgetListener::~MyWidgetListener() {
+// // Subscription gets deleted automatically and will deregister
+// // the callback in the process.
+// }
+//
+// private:
+// void OnFoo(const Foo& foo) {
+// // Do something.
+// }
+//
+// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
+// foo_subscription_;
+//
+// DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
+// };
+
+namespace base {
+
+namespace internal {
+
+template <typename CallbackType>
+class CallbackListBase {
+ public:
+ class Subscription {
+ public:
+ Subscription(CallbackListBase<CallbackType>* list,
+ typename std::list<CallbackType>::iterator iter)
+ : list_(list),
+ iter_(iter) {
+ }
+
+ ~Subscription() {
+ if (list_->active_iterator_count_) {
+ iter_->Reset();
+ } else {
+ list_->callbacks_.erase(iter_);
+ if (!list_->removal_callback_.is_null())
+ list_->removal_callback_.Run();
+ }
+ }
+
+ private:
+ CallbackListBase<CallbackType>* list_;
+ typename std::list<CallbackType>::iterator iter_;
+
+ DISALLOW_COPY_AND_ASSIGN(Subscription);
+ };
+
+ // Add a callback to the list. The callback will remain registered until the
+ // returned Subscription is destroyed, which must occur before the
+ // CallbackList is destroyed.
+ scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
+ DCHECK(!cb.is_null());
+ return scoped_ptr<Subscription>(
+ new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
+ }
+
+ // Sets a callback which will be run when a subscription list is changed.
+ void set_removal_callback(const Closure& callback) {
+ removal_callback_ = callback;
+ }
+
+ // Returns true if there are no subscriptions. This is only valid to call when
+ // not looping through the list.
+ bool empty() {
+ DCHECK_EQ(0, active_iterator_count_);
+ return callbacks_.empty();
+ }
+
+ protected:
+ // An iterator class that can be used to access the list of callbacks.
+ class Iterator {
+ public:
+ explicit Iterator(CallbackListBase<CallbackType>* list)
+ : list_(list),
+ list_iter_(list_->callbacks_.begin()) {
+ ++list_->active_iterator_count_;
+ }
+
+ Iterator(const Iterator& iter)
+ : list_(iter.list_),
+ list_iter_(iter.list_iter_) {
+ ++list_->active_iterator_count_;
+ }
+
+ ~Iterator() {
+ if (list_ && --list_->active_iterator_count_ == 0) {
+ list_->Compact();
+ }
+ }
+
+ CallbackType* GetNext() {
+ while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
+ ++list_iter_;
+
+ CallbackType* cb = NULL;
+ if (list_iter_ != list_->callbacks_.end()) {
+ cb = &(*list_iter_);
+ ++list_iter_;
+ }
+ return cb;
+ }
+
+ private:
+ CallbackListBase<CallbackType>* list_;
+ typename std::list<CallbackType>::iterator list_iter_;
+ };
+
+ CallbackListBase() : active_iterator_count_(0) {}
+
+ ~CallbackListBase() {
+ DCHECK_EQ(0, active_iterator_count_);
+ DCHECK_EQ(0U, callbacks_.size());
+ }
+
+ // Returns an instance of a CallbackListBase::Iterator which can be used
+ // to run callbacks.
+ Iterator GetIterator() {
+ return Iterator(this);
+ }
+
+ // Compact the list: remove any entries which were NULLed out during
+ // iteration.
+ void Compact() {
+ typename std::list<CallbackType>::iterator it = callbacks_.begin();
+ bool updated = false;
+ while (it != callbacks_.end()) {
+ if ((*it).is_null()) {
+ updated = true;
+ it = callbacks_.erase(it);
+ } else {
+ ++it;
+ }
+
+ if (updated && !removal_callback_.is_null())
+ removal_callback_.Run();
+ }
+ }
+
+ private:
+ std::list<CallbackType> callbacks_;
+ int active_iterator_count_;
+ Closure removal_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
+};
+
+} // namespace internal
+
+template <typename Sig> class CallbackList;
+
+template <typename... Args>
+class CallbackList<void(Args...)>
+ : public internal::CallbackListBase<Callback<void(Args...)> > {
+ public:
+ typedef Callback<void(Args...)> CallbackType;
+
+ CallbackList() {}
+
+ void Notify(
+ typename internal::CallbackParamTraits<Args>::ForwardType... args) {
+ typename internal::CallbackListBase<CallbackType>::Iterator it =
+ this->GetIterator();
+ CallbackType* cb;
+ while ((cb = it.GetNext()) != NULL) {
+ cb->Run(args...);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CallbackList);
+};
+
+} // namespace base
+
+#endif // BASE_CALLBACK_LIST_H_