Chromium Code Reviews| 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 |