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 |