| 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 | 10 |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/message_loop/message_loop_proxy.h" | |
| 18 #include "base/observer_list.h" | 17 #include "base/observer_list.h" |
| 18 #include "base/single_thread_task_runner.h" |
| 19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 20 #include "base/thread_task_runner_handle.h" |
| 20 #include "base/threading/platform_thread.h" | 21 #include "base/threading/platform_thread.h" |
| 21 | 22 |
| 22 /////////////////////////////////////////////////////////////////////////////// | 23 /////////////////////////////////////////////////////////////////////////////// |
| 23 // | 24 // |
| 24 // OVERVIEW: | 25 // OVERVIEW: |
| 25 // | 26 // |
| 26 // A thread-safe container for a list of observers. | 27 // A thread-safe container for a list of observers. |
| 27 // This is similar to the observer_list (see observer_list.h), but it | 28 // This is similar to the observer_list (see observer_list.h), but it |
| 28 // is more robust for multi-threaded situations. | 29 // is more robust for multi-threaded situations. |
| 29 // | 30 // |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 } | 202 } |
| 202 | 203 |
| 203 // TODO(mbelshe): Add more wrappers for Notify() with more arguments. | 204 // TODO(mbelshe): Add more wrappers for Notify() with more arguments. |
| 204 | 205 |
| 205 private: | 206 private: |
| 206 // See comment above ObserverListThreadSafeTraits' definition. | 207 // See comment above ObserverListThreadSafeTraits' definition. |
| 207 friend struct ObserverListThreadSafeTraits<ObserverType>; | 208 friend struct ObserverListThreadSafeTraits<ObserverType>; |
| 208 | 209 |
| 209 struct ObserverListContext { | 210 struct ObserverListContext { |
| 210 explicit ObserverListContext(NotificationType type) | 211 explicit ObserverListContext(NotificationType type) |
| 211 : loop(base::MessageLoopProxy::current()), | 212 : task_runner(base::ThreadTaskRunnerHandle::Get()), list(type) {} |
| 212 list(type) { | |
| 213 } | |
| 214 | 213 |
| 215 scoped_refptr<base::MessageLoopProxy> loop; | 214 scoped_refptr<base::SingleThreadTaskRunner> task_runner; |
| 216 ObserverList<ObserverType> list; | 215 ObserverList<ObserverType> list; |
| 217 | 216 |
| 218 DISALLOW_COPY_AND_ASSIGN(ObserverListContext); | 217 DISALLOW_COPY_AND_ASSIGN(ObserverListContext); |
| 219 }; | 218 }; |
| 220 | 219 |
| 221 ~ObserverListThreadSafe() { | 220 ~ObserverListThreadSafe() { |
| 222 STLDeleteValues(&observer_lists_); | 221 STLDeleteValues(&observer_lists_); |
| 223 } | 222 } |
| 224 | 223 |
| 225 template <class Method, class Params> | 224 template <class Method, class Params> |
| 226 void Notify(const UnboundMethod<ObserverType, Method, Params>& method) { | 225 void Notify(const UnboundMethod<ObserverType, Method, Params>& method) { |
| 227 base::AutoLock lock(list_lock_); | 226 base::AutoLock lock(list_lock_); |
| 228 typename ObserversListMap::iterator it; | 227 typename ObserversListMap::iterator it; |
| 229 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) { | 228 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) { |
| 230 ObserverListContext* context = (*it).second; | 229 ObserverListContext* context = (*it).second; |
| 231 context->loop->PostTask( | 230 context->task_runner->PostTask( |
| 232 FROM_HERE, | 231 FROM_HERE, |
| 233 base::Bind(&ObserverListThreadSafe<ObserverType>:: | 232 base::Bind(&ObserverListThreadSafe< |
| 234 template NotifyWrapper<Method, Params>, this, context, method)); | 233 ObserverType>::template NotifyWrapper<Method, Params>, |
| 234 this, |
| 235 context, |
| 236 method)); |
| 235 } | 237 } |
| 236 } | 238 } |
| 237 | 239 |
| 238 // Wrapper which is called to fire the notifications for each thread's | 240 // Wrapper which is called to fire the notifications for each thread's |
| 239 // ObserverList. This function MUST be called on the thread which owns | 241 // ObserverList. This function MUST be called on the thread which owns |
| 240 // the unsafe ObserverList. | 242 // the unsafe ObserverList. |
| 241 template <class Method, class Params> | 243 template <class Method, class Params> |
| 242 void NotifyWrapper(ObserverListContext* context, | 244 void NotifyWrapper(ObserverListContext* context, |
| 243 const UnboundMethod<ObserverType, Method, Params>& method) { | 245 const UnboundMethod<ObserverType, Method, Params>& method) { |
| 244 | 246 |
| 245 // Check that this list still needs notifications. | 247 // Check that this list still needs notifications. |
| 246 { | 248 { |
| 247 base::AutoLock lock(list_lock_); | 249 base::AutoLock lock(list_lock_); |
| 248 typename ObserversListMap::iterator it = | 250 typename ObserversListMap::iterator it = |
| 249 observer_lists_.find(base::PlatformThread::CurrentId()); | 251 observer_lists_.find(base::PlatformThread::CurrentId()); |
| 250 | 252 |
| 251 // The ObserverList could have been removed already. In fact, it could | 253 // The ObserverList could have been removed already. In fact, it could |
| 252 // have been removed and then re-added! If the master list's loop | 254 // have been removed and then re-added! If the master list's task runner |
| 253 // does not match this one, then we do not need to finish this | 255 // does not match this one, then we do not need to finish this |
| 254 // notification. | 256 // notification. |
| 255 if (it == observer_lists_.end() || it->second != context) | 257 if (it == observer_lists_.end() || it->second != context) |
| 256 return; | 258 return; |
| 257 } | 259 } |
| 258 | 260 |
| 259 { | 261 { |
| 260 typename ObserverList<ObserverType>::Iterator it(context->list); | 262 typename ObserverList<ObserverType>::Iterator it(context->list); |
| 261 ObserverType* obs; | 263 ObserverType* obs; |
| 262 while ((obs = it.GetNext()) != NULL) | 264 while ((obs = it.GetNext()) != NULL) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 286 ObserversListMap; | 288 ObserversListMap; |
| 287 | 289 |
| 288 mutable base::Lock list_lock_; // Protects the observer_lists_. | 290 mutable base::Lock list_lock_; // Protects the observer_lists_. |
| 289 ObserversListMap observer_lists_; | 291 ObserversListMap observer_lists_; |
| 290 const NotificationType type_; | 292 const NotificationType type_; |
| 291 | 293 |
| 292 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); | 294 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); |
| 293 }; | 295 }; |
| 294 | 296 |
| 295 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ | 297 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ |
| OLD | NEW |