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 |