OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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_ |
OLD | NEW |