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. So, it safely handles the case of an callback removing itself | |
awong
2013/09/04 17:44:35
So, it safely -> It safely
Cait (Slow)
2013/09/04 22:09:25
Done.
| |
24 // or other 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 // // TODO (caitkp): A less clunky approach here? | |
Avi (use Gerrit)
2013/08/30 19:49:48
How would this be less clunky?
ScopedClosureRunne
awong
2013/09/04 17:44:35
Agreed...I think we can remove this comment.
Cait (Slow)
2013/09/04 22:09:25
Done.
| |
51 // remove_foo_callback_.Reset( | |
52 // MyWidget::GetCurrent()->RegisterCallback( | |
53 // base::Bind(&MyWidgetListener::OnFoo, this))); | |
54 // } | |
55 // | |
56 // MyWidgetListener::~MyWidgetListener() { | |
57 // // ScopedClosureRunner runs its closure automatically on deletion. | |
58 // } | |
59 // | |
60 // void OnFoo(const Foo& foo) { | |
61 // // Do something. | |
62 // } | |
63 // | |
64 // private: | |
65 // base::ScopedClosureRunner remove_foo_callback_; | |
66 // }; | |
67 | |
68 namespace base { | |
69 template <typename Detail> | |
70 class CallbackListWithDetails { | |
71 public: | |
72 typedef base::Callback<void(const Detail&)> CallbackType; | |
73 | |
74 explicit CallbackListWithDetails(CallbackNotificationType type) | |
75 : list_impl_(new base::internal::CallbackListImpl(type)) {} | |
76 | |
77 ~CallbackListWithDetails() {} | |
78 | |
79 // Add a callback to the list. A callback should not be added to | |
80 // the same list more than once. The returned closure (used to remove the | |
81 // callback from the list) is guaranteed to be safe to run. | |
82 base::Closure Add(const CallbackType& cb) { | |
83 DCHECK(!cb.is_null()); | |
84 return list_impl_->AddCallback(new CallbackType(cb)); | |
85 } | |
86 | |
87 // Execute all active (non-null) callbacks with |details| parameter. | |
88 void Run(const Detail& details) { | |
89 if (might_have_callbacks()) { | |
90 internal::CallbackListImpl::Iterator it(list_impl_->GetWeakPtr()); | |
awong
2013/09/04 17:44:35
I still feel like this should just be:
list_imp
Cait (Slow)
2013/09/04 22:09:25
Done.
| |
91 CallbackType* cb; | |
92 while((cb = static_cast<CallbackType*>(it.GetNext())) != NULL) { | |
awong
2013/09/04 17:44:35
Add a comment explaining why we know this static_c
Cait (Slow)
2013/09/04 22:09:25
Done.
| |
93 cb->Run(details); | |
94 } | |
95 } | |
96 } | |
97 | |
98 // Delete (or nullify, if called during iteration), all callbacks in the list. | |
99 void Clear() { | |
100 list_impl_->Clear(); | |
101 } | |
102 | |
103 bool might_have_callbacks() { | |
104 return list_impl_->might_have_callbacks(); | |
105 } | |
106 | |
107 private: | |
108 scoped_ptr<base::internal::CallbackListImpl> list_impl_; | |
awong
2013/09/04 17:44:35
This doesn't seem like it needs to be dynamically
Cait (Slow)
2013/09/04 22:09:25
Done.
| |
109 | |
110 DISALLOW_COPY_AND_ASSIGN(CallbackListWithDetails); | |
111 }; | |
112 | |
113 class CallbackList { | |
114 public: | |
115 explicit CallbackList(CallbackNotificationType type); | |
116 | |
117 ~CallbackList(); | |
118 | |
119 // Add a callback to the list. A callback should not be added to | |
120 // the same list more than once. The returned closure (used to remove the | |
121 // callback from the list) is guaranteed to be safe to run. | |
122 base::Closure Add(const base::Closure& cb); | |
123 | |
124 // Execute all active (non-null) callbacks. | |
125 void Run(); | |
126 | |
127 // Delete (or nullify, if called during iteration), all callbacks in the list. | |
128 void Clear(); | |
129 | |
130 bool might_have_callbacks(); | |
131 | |
132 private: | |
133 scoped_ptr<base::internal::CallbackListImpl> list_impl_; | |
134 | |
135 DISALLOW_COPY_AND_ASSIGN(CallbackList); | |
136 }; | |
137 | |
138 } // namespace base | |
139 | |
140 #endif // BASE_CALLBACK_LIST_H_ | |
OLD | NEW |