| 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 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 void AssertEmpty() const { | 160 void AssertEmpty() const { |
| 161 base::AutoLock lock(list_lock_); | 161 base::AutoLock lock(list_lock_); |
| 162 DCHECK(observer_lists_.empty()); | 162 DCHECK(observer_lists_.empty()); |
| 163 } | 163 } |
| 164 | 164 |
| 165 // Notify methods. | 165 // Notify methods. |
| 166 // Make a thread-safe callback to each Observer in the list. | 166 // Make a thread-safe callback to each Observer in the list. |
| 167 // Note, these calls are effectively asynchronous. You cannot assume | 167 // Note, these calls are effectively asynchronous. You cannot assume |
| 168 // 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 |
| 169 // been Notified. The notification may still be pending delivery. | 169 // been Notified. The notification may still be pending delivery. |
| 170 template <class Method> | 170 template <class Method, class... Params> |
| 171 void Notify(Method m) { | 171 void Notify(Method m, const Params&... params) { |
| 172 UnboundMethod<ObserverType, Method, Tuple0> method(m, MakeTuple()); | 172 UnboundMethod<ObserverType, Method, Tuple<Params...>> method( |
| 173 Notify<Method, Tuple0>(method); | 173 m, MakeTuple(params...)); |
| 174 |
| 175 base::AutoLock lock(list_lock_); |
| 176 for (const auto& entry : observer_lists_) { |
| 177 ObserverListContext* context = entry.second; |
| 178 context->loop->PostTask( |
| 179 FROM_HERE, |
| 180 base::Bind( |
| 181 &ObserverListThreadSafe<ObserverType>::template NotifyWrapper< |
| 182 Method, Tuple<Params...>>, |
| 183 this, context, method)); |
| 184 } |
| 174 } | 185 } |
| 175 | 186 |
| 176 template <class Method, class A> | |
| 177 void Notify(Method m, const A& a) { | |
| 178 UnboundMethod<ObserverType, Method, Tuple1<A> > method(m, MakeTuple(a)); | |
| 179 Notify<Method, Tuple1<A> >(method); | |
| 180 } | |
| 181 | |
| 182 template <class Method, class A, class B> | |
| 183 void Notify(Method m, const A& a, const B& b) { | |
| 184 UnboundMethod<ObserverType, Method, Tuple2<A, B> > method( | |
| 185 m, MakeTuple(a, b)); | |
| 186 Notify<Method, Tuple2<A, B> >(method); | |
| 187 } | |
| 188 | |
| 189 template <class Method, class A, class B, class C> | |
| 190 void Notify(Method m, const A& a, const B& b, const C& c) { | |
| 191 UnboundMethod<ObserverType, Method, Tuple3<A, B, C> > method( | |
| 192 m, MakeTuple(a, b, c)); | |
| 193 Notify<Method, Tuple3<A, B, C> >(method); | |
| 194 } | |
| 195 | |
| 196 template <class Method, class A, class B, class C, class D> | |
| 197 void Notify(Method m, const A& a, const B& b, const C& c, const D& d) { | |
| 198 UnboundMethod<ObserverType, Method, Tuple4<A, B, C, D> > method( | |
| 199 m, MakeTuple(a, b, c, d)); | |
| 200 Notify<Method, Tuple4<A, B, C, D> >(method); | |
| 201 } | |
| 202 | |
| 203 // TODO(mbelshe): Add more wrappers for Notify() with more arguments. | |
| 204 | |
| 205 private: | 187 private: |
| 206 // See comment above ObserverListThreadSafeTraits' definition. | 188 // See comment above ObserverListThreadSafeTraits' definition. |
| 207 friend struct ObserverListThreadSafeTraits<ObserverType>; | 189 friend struct ObserverListThreadSafeTraits<ObserverType>; |
| 208 | 190 |
| 209 struct ObserverListContext { | 191 struct ObserverListContext { |
| 210 explicit ObserverListContext(NotificationType type) | 192 explicit ObserverListContext(NotificationType type) |
| 211 : loop(base::MessageLoopProxy::current()), | 193 : loop(base::MessageLoopProxy::current()), |
| 212 list(type) { | 194 list(type) { |
| 213 } | 195 } |
| 214 | 196 |
| 215 scoped_refptr<base::MessageLoopProxy> loop; | 197 scoped_refptr<base::MessageLoopProxy> loop; |
| 216 ObserverList<ObserverType> list; | 198 ObserverList<ObserverType> list; |
| 217 | 199 |
| 218 DISALLOW_COPY_AND_ASSIGN(ObserverListContext); | 200 DISALLOW_COPY_AND_ASSIGN(ObserverListContext); |
| 219 }; | 201 }; |
| 220 | 202 |
| 221 ~ObserverListThreadSafe() { | 203 ~ObserverListThreadSafe() { |
| 222 STLDeleteValues(&observer_lists_); | 204 STLDeleteValues(&observer_lists_); |
| 223 } | 205 } |
| 224 | 206 |
| 225 template <class Method, class Params> | |
| 226 void Notify(const UnboundMethod<ObserverType, Method, Params>& method) { | |
| 227 base::AutoLock lock(list_lock_); | |
| 228 typename ObserversListMap::iterator it; | |
| 229 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) { | |
| 230 ObserverListContext* context = (*it).second; | |
| 231 context->loop->PostTask( | |
| 232 FROM_HERE, | |
| 233 base::Bind(&ObserverListThreadSafe<ObserverType>:: | |
| 234 template NotifyWrapper<Method, Params>, this, context, method)); | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 // Wrapper which is called to fire the notifications for each thread's | 207 // Wrapper which is called to fire the notifications for each thread's |
| 239 // ObserverList. This function MUST be called on the thread which owns | 208 // ObserverList. This function MUST be called on the thread which owns |
| 240 // the unsafe ObserverList. | 209 // the unsafe ObserverList. |
| 241 template <class Method, class Params> | 210 template <class Method, class Params> |
| 242 void NotifyWrapper(ObserverListContext* context, | 211 void NotifyWrapper(ObserverListContext* context, |
| 243 const UnboundMethod<ObserverType, Method, Params>& method) { | 212 const UnboundMethod<ObserverType, Method, Params>& method) { |
| 244 | 213 |
| 245 // Check that this list still needs notifications. | 214 // Check that this list still needs notifications. |
| 246 { | 215 { |
| 247 base::AutoLock lock(list_lock_); | 216 base::AutoLock lock(list_lock_); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 ObserversListMap; | 255 ObserversListMap; |
| 287 | 256 |
| 288 mutable base::Lock list_lock_; // Protects the observer_lists_. | 257 mutable base::Lock list_lock_; // Protects the observer_lists_. |
| 289 ObserversListMap observer_lists_; | 258 ObserversListMap observer_lists_; |
| 290 const NotificationType type_; | 259 const NotificationType type_; |
| 291 | 260 |
| 292 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); | 261 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); |
| 293 }; | 262 }; |
| 294 | 263 |
| 295 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ | 264 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ |
| OLD | NEW |