OLD | NEW |
---|---|
(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_LIST_H_ | |
6 #define BASE_CALLBACK_LIST_H_ | |
7 | |
8 #include <algorithm> | |
9 #include <limits> | |
10 #include <vector> | |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/bind.h" | |
14 #include "base/callback.h" | |
15 #include "base/callback_list_internal.h" | |
16 #include "base/memory/scoped_ptr.h" | |
17 #include "base/memory/weak_ptr.h" | |
18 | |
19 // OVERVIEW: | |
20 // | |
21 // A container for a list of callbacks. Unlike a normal STL vector or list, | |
22 // this container can be modified during iteration without invalidating the | |
23 // iterator. It safely handles the case of a callback removing itself | |
24 // or another callback from the list while callbacks are being run. | |
25 // | |
26 // TYPICAL USAGE: | |
27 // | |
28 // class MyWidget { | |
29 // public: | |
30 // ... | |
31 // | |
32 // typedef base::Callback<void(const Foo&)> OnFooCallback; | |
33 // | |
34 // base::Closure RegisterCallback(const OnFooCallback& cb) { | |
35 // return callback_list_.Add(cb); | |
36 // } | |
37 // | |
38 // private: | |
39 // void NotifyFoo(const Foo& foo) { | |
40 // callback_list_.Run(foo); | |
41 // } | |
42 // | |
43 // CallbackList<Foo> callback_list_(CallbackList<Foo>::NOTIFY_ALL); | |
44 // }; | |
45 // | |
46 // | |
47 // class MyWidgetListener { | |
48 // public: | |
49 // MyWidgetListener::MyWidgetListener() { | |
50 // remove_foo_callback_.Reset( | |
51 // MyWidget::GetCurrent()->RegisterCallback( | |
52 // base::Bind(&MyWidgetListener::OnFoo, this))); | |
53 // } | |
54 // | |
55 // MyWidgetListener::~MyWidgetListener() { | |
56 // // ScopedClosureRunner runs its closure automatically on deletion. | |
57 // } | |
58 // | |
59 // void OnFoo(const Foo& foo) { | |
60 // // Do something. | |
61 // } | |
62 // | |
63 // private: | |
64 // base::ScopedClosureRunner remove_foo_callback_; | |
65 // }; | |
66 | |
67 namespace base { | |
68 | |
69 template <typename CallbackType> | |
70 class CallbackListBase { | |
awong
2013/09/04 23:20:07
CallbackListBase should be in base::internal.
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
71 public: | |
72 // Add a callback to the list. A callback should not be added to | |
73 // the same list more than once. The returned closure (used to remove the | |
74 // callback from the list) is guaranteed to be safe to run. | |
75 base::Closure Add(const CallbackType& cb) WARN_UNUSED_RESULT { | |
awong
2013/09/04 23:20:07
I'm going to slightly disagree with erikwright her
erikwright (departed)
2013/09/05 14:14:31
AIUI, the general model is publisher lifetime exce
Avi (use Gerrit)
2013/09/05 15:03:48
Or a ScopedClosureRunner? Same basic philosophy as
awong
2013/09/05 17:42:17
I see what you're saying but I'm not completely co
| |
76 DCHECK(!cb.is_null()); | |
77 return list_impl_.Add(new CallbackType(cb)); | |
78 } | |
79 | |
80 // Delete all callbacks in the list. | |
81 void Clear() { | |
82 list_impl_.Clear(); | |
83 } | |
84 | |
85 // Assert that the list is empty and no iterators are active. | |
86 void AssertEmpty() { | |
87 list_impl_.AssertEmpty(); | |
88 } | |
89 | |
90 protected: | |
91 CallbackListBase() {} | |
92 | |
93 // Get an iterator to the CallbackList. | |
94 scoped_ptr<internal::CallbackListImpl::Iterator> GetIterator() { | |
95 return list_impl_.GetIterator(); | |
96 } | |
97 | |
98 private: | |
99 base::internal::CallbackListImpl list_impl_; | |
100 | |
101 DISALLOW_COPY_AND_ASSIGN(CallbackListBase); | |
102 }; | |
103 | |
104 template <typename Details> | |
105 class CallbackList : public CallbackListBase<Callback<void(const Details&)> > { | |
106 public: | |
107 typedef base::Callback<void(const Details&)> CallbackType; | |
108 | |
109 CallbackList() : CallbackListBase<CallbackType>() {} | |
awong
2013/09/04 23:20:07
There's no need to explicitly call the default con
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
110 | |
111 // Execute all active callbacks with |details| parameter. | |
112 void Run(const Details& details) { | |
113 scoped_ptr<internal::CallbackListImpl::Iterator> it = this->GetIterator(); | |
awong
2013/09/04 23:20:07
indentation.
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
114 CallbackType* cb; | |
115 // static_cast is safe here, all callbacks were added via | |
awong
2013/09/04 23:20:07
here, all -> here. All
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
116 // CallbackListBase::Add and so must be of type | |
awong
2013/09/04 23:20:07
::Add -> ::Add()
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
117 // Callback<void(const Details&)>. | |
118 while((cb = static_cast<CallbackType*>(it->GetNext())) != | |
awong
2013/09/04 23:20:07
This can fit on one line.
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
119 NULL) { | |
120 cb->Run(details); | |
121 } | |
122 } | |
123 | |
124 private: | |
125 DISALLOW_COPY_AND_ASSIGN(CallbackList); | |
126 }; | |
127 | |
128 template <> class CallbackList<void> : public CallbackListBase<Closure> { | |
129 public: | |
130 CallbackList() : CallbackListBase<Closure>() {} | |
awong
2013/09/04 23:20:07
Remove explicit invocation of base class's default
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
131 | |
132 // Execute all active callbacks. | |
133 void Run() { | |
134 scoped_ptr<internal::CallbackListImpl::Iterator> it = GetIterator(); | |
135 Closure* cb; | |
136 // static_cast is safe here, all callbacks were added via | |
awong
2013/09/04 23:20:07
here, all -> here. All
Cait (Slow)
2013/09/06 18:41:46
Done.
| |
137 // CallbackListBase::Add and so must be Closures. | |
138 while((cb = static_cast<Closure*>(it->GetNext())) != NULL) { | |
139 cb->Run(); | |
140 } | |
141 } | |
142 | |
143 private: | |
144 DISALLOW_COPY_AND_ASSIGN(CallbackList); | |
145 }; | |
146 | |
147 } // namespace base | |
148 | |
149 #endif // BASE_CALLBACK_LIST_H_ | |
OLD | NEW |