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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CALLBACK_REGISTRY_INTERNAL_H_
6 #define BASE_CALLBACK_REGISTRY_INTERNAL_H_
7
8 #include <limits>
9 #include <list>
10
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/callback_handle.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h"
16
17 namespace base {
18 namespace internal {
19 // Holds the methods shared by all specializations of CallbackRegistry to avoid
20 // code duplication.
21 //
22 // 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.
23 // use it directly.
24 template <typename CallbackType>
25 class CallbackRegistryBase {
26 public:
27 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.
28 AssertEmpty();
29 }
30
31 // Add a callback to the list. A callback should not be added to
32 // 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.
33 // 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.
34 // the handle will automatically deregister the callback.
35 scoped_ptr<CallbackHandle> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
36 DCHECK(!cb.is_null());
37 typename ListType::iterator it = callbacks_.insert(callbacks_.end(), cb);
38 return scoped_ptr<CallbackHandle>(new HandleImpl(this, it));
39 }
40
41 // Assert that the list is empty and no iterators are active.
42 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.
43 DCHECK(active_iterator_count_ == 0 && callbacks_.size() == 0);
44 }
45
46 protected:
47 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).
48
49 // An iterator class that can be used to access the list of callbacks.
50 class Iterator {
51 public:
52 explicit Iterator(CallbackRegistryBase<CallbackType>* list)
53 : list_(list),
54 list_iter_(list_->callbacks_.begin()) {
55 ++list_->active_iterator_count_;
56 }
57
58 Iterator(const Iterator& iter)
59 : list_(iter.list_),
60 list_iter_(iter.list_iter_) {
61 ++list_->active_iterator_count_;
62 }
63
64 ~Iterator() {
65 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.
66 list_->Compact();
67 }
68 }
69
70 CallbackType* GetNext() {
71 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.
72 return NULL;
73 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.
74 list_iter_++;
75
76 CallbackType* cb =
77 list_iter_ != list_->callbacks_.end() ? &(*list_iter_) : NULL;
78 list_iter_++;
79 return cb;
80 }
81
82 private:
83 CallbackRegistryBase<CallbackType>* list_;
84 typename ListType::iterator list_iter_;
85
erikwright (departed) 2013/09/06 21:01:07 remove blank line
Cait (Slow) 2013/09/06 22:17:11 Done.
86 };
87
88 CallbackRegistryBase()
89 : active_iterator_count_(0) {}
90
91 // Returns an instance of a CallbackRegistryBase::Iterator which can be used
92 // to run callbacks.
93 Iterator GetIterator() {
94 return Iterator(this);
95 }
96
97 // Compact the list: remove any entries which were NULLed out during
98 // iteration.
99 void Compact() {
100 typename ListType::iterator it = callbacks_.begin();
101 while (it != callbacks_.end()) {
102 if ((*it).is_null())
103 it = callbacks_.erase(it);
104 else
105 ++it;
106 }
107 }
108
109 private:
110 class HandleImpl : public CallbackHandle {
111 public:
112 HandleImpl(CallbackRegistryBase<CallbackType>* list,
113 typename ListType::iterator iter)
114 : list_(list),
115 iter_(iter) {}
116
117 ~HandleImpl() {
118 if (list_->active_iterator_count_)
119 (*iter_).Reset();
120 else
121 list_->callbacks_.erase(iter_);
122 }
123
124 private:
125 CallbackRegistryBase<CallbackType>* list_;
126 typename ListType::iterator iter_;
127 };
erikwright (departed) 2013/09/06 21:01:07 DISALLOW...
Cait (Slow) 2013/09/06 22:17:11 Done.
128
129 ListType callbacks_;
130 int active_iterator_count_;
131
132 DISALLOW_COPY_AND_ASSIGN(CallbackRegistryBase);
133 };
134
135 } // namespace internal
136 } // namespace base
137
138 #endif // BASE_CALLBACK_REGISTRY_INTERNAL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698