Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1696)

Unified Diff: base/callback_registry_internal.h

Issue 22877038: Add a CallbackRegistry class to base/ to manage callbacks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: List --> Registry, Closure --> Handle Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/callback_registry_internal.h
diff --git a/base/callback_registry_internal.h b/base/callback_registry_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b87943ffc94d1634e53601328d4706e3f3c3df2
--- /dev/null
+++ b/base/callback_registry_internal.h
@@ -0,0 +1,138 @@
+// 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_REGISTRY_INTERNAL_H_
+#define BASE_CALLBACK_REGISTRY_INTERNAL_H_
+
+#include <limits>
+#include <list>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/callback_handle.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+
+namespace base {
+namespace internal {
+// Holds the methods shared by all specializations of CallbackRegistry to avoid
+// code duplication.
+//
+// This class is meant as an implementation detail for CallbackRegistry do not
erikwright (departed) 2013/09/06 21:01:07 "do" should start a new sentence (be preceded by a
Cait (Slow) 2013/09/06 22:17:11 Done.
+// use it directly.
+template <typename CallbackType>
+class CallbackRegistryBase {
+ public:
+ virtual ~CallbackRegistryBase() {
awong 2013/09/06 19:03:24 No need for virtual since no one should have a poi
Cait (Slow) 2013/09/06 22:17:11 Done.
+ AssertEmpty();
+ }
+
+ // Add a callback to the list. A callback should not be added to
+ // the same list more than once. The returned handle should be retained until
erikwright (departed) 2013/09/06 21:01:07 The warning against adding a callback more than on
Cait (Slow) 2013/09/06 22:17:11 Done.
+ // the listener wishes to deregister the callback, at which point, deleting
erikwright (departed) 2013/09/06 21:01:07 The bit about the returned handle is a bit repetit
Cait (Slow) 2013/09/06 22:17:11 Done.
+ // the handle will automatically deregister the callback.
+ scoped_ptr<CallbackHandle> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
+ DCHECK(!cb.is_null());
+ typename ListType::iterator it = callbacks_.insert(callbacks_.end(), cb);
+ return scoped_ptr<CallbackHandle>(new HandleImpl(this, it));
+ }
+
+ // Assert that the list is empty and no iterators are active.
+ void AssertEmpty() {
awong 2013/09/06 19:03:24 Make this protected?
erikwright (departed) 2013/09/06 21:01:07 I would actually just inline it in the destructor.
Cait (Slow) 2013/09/06 22:17:11 Done.
Cait (Slow) 2013/09/06 22:17:11 Done.
+ DCHECK(active_iterator_count_ == 0 && callbacks_.size() == 0);
+ }
+
+ protected:
+ typedef std::list<CallbackType> ListType;
awong 2013/09/06 19:03:24 nit: maybe use std::slist?
erikwright (departed) 2013/09/06 21:01:07 That would make removal O(N).
+
+ // An iterator class that can be used to access the list of callbacks.
+ class Iterator {
+ public:
+ explicit Iterator(CallbackRegistryBase<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) {
erikwright (departed) 2013/09/06 21:01:07 also here, list_ is never null
Cait (Slow) 2013/09/06 22:17:11 Done.
+ list_->Compact();
+ }
+ }
+
+ CallbackType* GetNext() {
+ if (!list_)
awong 2013/09/06 19:03:24 I don't think it's possible for list_ to be NULL.
Cait (Slow) 2013/09/06 22:17:11 Done.
+ return NULL;
+ while ((list_iter_ != list_->callbacks_.end()) && (*list_iter_).is_null())
erikwright (departed) 2013/09/06 21:01:07 '(*list_iter_).' -> 'list_iter_->'
Cait (Slow) 2013/09/06 22:17:11 Done.
+ list_iter_++;
+
+ CallbackType* cb =
+ list_iter_ != list_->callbacks_.end() ? &(*list_iter_) : NULL;
+ list_iter_++;
+ return cb;
+ }
+
+ private:
+ CallbackRegistryBase<CallbackType>* list_;
+ typename ListType::iterator list_iter_;
+
erikwright (departed) 2013/09/06 21:01:07 remove blank line
Cait (Slow) 2013/09/06 22:17:11 Done.
+ };
+
+ CallbackRegistryBase()
+ : active_iterator_count_(0) {}
+
+ // Returns an instance of a CallbackRegistryBase::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 ListType::iterator it = callbacks_.begin();
+ while (it != callbacks_.end()) {
+ if ((*it).is_null())
+ it = callbacks_.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ private:
+ class HandleImpl : public CallbackHandle {
+ public:
+ HandleImpl(CallbackRegistryBase<CallbackType>* list,
+ typename ListType::iterator iter)
+ : list_(list),
+ iter_(iter) {}
+
+ ~HandleImpl() {
+ if (list_->active_iterator_count_)
+ (*iter_).Reset();
+ else
+ list_->callbacks_.erase(iter_);
+ }
+
+ private:
+ CallbackRegistryBase<CallbackType>* list_;
+ typename ListType::iterator iter_;
+ };
erikwright (departed) 2013/09/06 21:01:07 DISALLOW...
Cait (Slow) 2013/09/06 22:17:11 Done.
+
+ ListType callbacks_;
+ int active_iterator_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallbackRegistryBase);
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_CALLBACK_REGISTRY_INTERNAL_H_

Powered by Google App Engine
This is Rietveld 408576698