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

Side by Side Diff: base/observer_list_threadsafe.h

Issue 2268283002: Replace DispatchToMethod in ObserverListThreadSafe with Bind (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_OBSERVER_LIST_THREADSAFE_H_ 5 #ifndef BASE_OBSERVER_LIST_THREADSAFE_H_
6 #define BASE_OBSERVER_LIST_THREADSAFE_H_ 6 #define BASE_OBSERVER_LIST_THREADSAFE_H_
7 7
8 #include <algorithm> 8 #include <algorithm>
9 #include <map> 9 #include <map>
10 #include <tuple> 10 #include <tuple>
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 /////////////////////////////////////////////////////////////////////////////// 54 ///////////////////////////////////////////////////////////////////////////////
55 55
56 namespace base { 56 namespace base {
57 57
58 // Forward declaration for ObserverListThreadSafeTraits. 58 // Forward declaration for ObserverListThreadSafeTraits.
59 template <class ObserverType> 59 template <class ObserverType>
60 class ObserverListThreadSafe; 60 class ObserverListThreadSafe;
61 61
62 namespace internal { 62 namespace internal {
63 63
64 // An UnboundMethod is a wrapper for a method where the actual object is 64 template <typename ObserverType, typename Method>
65 // provided at Run dispatch time. 65 struct Dispatcher;
66 template <class T, class Method, class Params> 66
67 class UnboundMethod { 67 template <typename ObserverType, typename ReceiverType, typename... Params>
68 public: 68 struct Dispatcher<ObserverType, void(ReceiverType::*)(Params...)> {
69 UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { 69 static void Run(void(ReceiverType::* m)(Params...),
70 static_assert((internal::ParamsUseScopedRefptrCorrectly<Params>::value), 70 Params... params, ObserverType* obj) {
71 "bad unbound method params"); 71 (obj->*m)(std::forward<Params>(params)...);
dcheng 2016/08/24 21:18:27 If I understand correctly, the reason this is safe
tzik 2016/08/25 00:53:01 Yes, it's done in Bind().
72 } 72 }
73 void Run(T* obj) const {
74 DispatchToMethod(obj, m_, p_);
75 }
76 private:
77 Method m_;
78 Params p_;
79 }; 73 };
80 74
81 } // namespace internal 75 } // namespace internal
82 76
83 // This class is used to work around VS2005 not accepting: 77 // This class is used to work around VS2005 not accepting:
84 // 78 //
85 // friend class 79 // friend class
86 // base::RefCountedThreadSafe<ObserverListThreadSafe<ObserverType>>; 80 // base::RefCountedThreadSafe<ObserverListThreadSafe<ObserverType>>;
87 // 81 //
88 // Instead of friending the class, we could friend the actual function 82 // Instead of friending the class, we could friend the actual function
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 void AssertEmpty() const { 160 void AssertEmpty() const {
167 AutoLock lock(list_lock_); 161 AutoLock lock(list_lock_);
168 DCHECK(observer_lists_.empty()); 162 DCHECK(observer_lists_.empty());
169 } 163 }
170 164
171 // Notify methods. 165 // Notify methods.
172 // Make a thread-safe callback to each Observer in the list. 166 // Make a thread-safe callback to each Observer in the list.
173 // Note, these calls are effectively asynchronous. You cannot assume 167 // Note, these calls are effectively asynchronous. You cannot assume
174 // that at the completion of the Notify call that all Observers have 168 // that at the completion of the Notify call that all Observers have
175 // been Notified. The notification may still be pending delivery. 169 // been Notified. The notification may still be pending delivery.
176 template <class Method, class... Params> 170 template <typename Method, typename... Params>
177 void Notify(const tracked_objects::Location& from_here, 171 void Notify(const tracked_objects::Location& from_here,
178 Method m, 172 Method m, Params&&... params) {
179 const Params&... params) { 173 Callback<void(ObserverType*)> method =
180 internal::UnboundMethod<ObserverType, Method, std::tuple<Params...>> method( 174 Bind(&internal::Dispatcher<ObserverType, Method>::Run,
181 m, std::make_tuple(params...)); 175 m, std::forward<Params>(params)...);
182 176
183 AutoLock lock(list_lock_); 177 AutoLock lock(list_lock_);
184 for (const auto& entry : observer_lists_) { 178 for (const auto& entry : observer_lists_) {
185 ObserverListContext* context = entry.second; 179 ObserverListContext* context = entry.second;
186 context->task_runner->PostTask( 180 context->task_runner->PostTask(
187 from_here, 181 from_here,
188 Bind(&ObserverListThreadSafe<ObserverType>::template NotifyWrapper< 182 Bind(&ObserverListThreadSafe<ObserverType>::NotifyWrapper,
189 Method, std::tuple<Params...>>,
190 this, context, method)); 183 this, context, method));
191 } 184 }
192 } 185 }
193 186
194 private: 187 private:
195 // See comment above ObserverListThreadSafeTraits' definition. 188 // See comment above ObserverListThreadSafeTraits' definition.
196 friend struct ObserverListThreadSafeTraits<ObserverType>; 189 friend struct ObserverListThreadSafeTraits<ObserverType>;
197 190
198 struct ObserverListContext { 191 struct ObserverListContext {
199 explicit ObserverListContext(NotificationType type) 192 explicit ObserverListContext(NotificationType type)
200 : task_runner(ThreadTaskRunnerHandle::Get()), list(type) {} 193 : task_runner(ThreadTaskRunnerHandle::Get()), list(type) {}
201 194
202 scoped_refptr<SingleThreadTaskRunner> task_runner; 195 scoped_refptr<SingleThreadTaskRunner> task_runner;
203 ObserverList<ObserverType> list; 196 ObserverList<ObserverType> list;
204 197
205 private: 198 private:
206 DISALLOW_COPY_AND_ASSIGN(ObserverListContext); 199 DISALLOW_COPY_AND_ASSIGN(ObserverListContext);
207 }; 200 };
208 201
209 ~ObserverListThreadSafe() { 202 ~ObserverListThreadSafe() {
210 STLDeleteValues(&observer_lists_); 203 STLDeleteValues(&observer_lists_);
211 } 204 }
212 205
213 // Wrapper which is called to fire the notifications for each thread's 206 // Wrapper which is called to fire the notifications for each thread's
214 // ObserverList. This function MUST be called on the thread which owns 207 // ObserverList. This function MUST be called on the thread which owns
215 // the unsafe ObserverList. 208 // the unsafe ObserverList.
216 template <class Method, class Params> 209 void NotifyWrapper(ObserverListContext* context,
217 void NotifyWrapper( 210 const Callback<void(ObserverType*)>& method) {
218 ObserverListContext* context,
219 const internal::UnboundMethod<ObserverType, Method, Params>& method) {
220 // Check that this list still needs notifications. 211 // Check that this list still needs notifications.
221 { 212 {
222 AutoLock lock(list_lock_); 213 AutoLock lock(list_lock_);
223 typename ObserversListMap::iterator it = 214 typename ObserversListMap::iterator it =
224 observer_lists_.find(PlatformThread::CurrentId()); 215 observer_lists_.find(PlatformThread::CurrentId());
225 216
226 // The ObserverList could have been removed already. In fact, it could 217 // The ObserverList could have been removed already. In fact, it could
227 // have been removed and then re-added! If the master list's loop 218 // have been removed and then re-added! If the master list's loop
228 // does not match this one, then we do not need to finish this 219 // does not match this one, then we do not need to finish this
229 // notification. 220 // notification.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 mutable Lock list_lock_; // Protects the observer_lists_. 255 mutable Lock list_lock_; // Protects the observer_lists_.
265 ObserversListMap observer_lists_; 256 ObserversListMap observer_lists_;
266 const NotificationType type_; 257 const NotificationType type_;
267 258
268 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); 259 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe);
269 }; 260 };
270 261
271 } // namespace base 262 } // namespace base
272 263
273 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ 264 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698