| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 // Add an observer to the list. | 86 // Add an observer to the list. |
| 87 void AddObserver(ObserverType* obs) { | 87 void AddObserver(ObserverType* obs) { |
| 88 ObserverList<ObserverType>* list = NULL; | 88 ObserverList<ObserverType>* list = NULL; |
| 89 MessageLoop* loop = MessageLoop::current(); | 89 MessageLoop* loop = MessageLoop::current(); |
| 90 // TODO(mbelshe): Get rid of this check. Its needed right now because | 90 // TODO(mbelshe): Get rid of this check. Its needed right now because |
| 91 // Time currently triggers usage of the ObserverList. | 91 // Time currently triggers usage of the ObserverList. |
| 92 // And unittests use time without a MessageLoop. | 92 // And unittests use time without a MessageLoop. |
| 93 if (!loop) | 93 if (!loop) |
| 94 return; // Some unittests may access this without a message loop. | 94 return; // Some unittests may access this without a message loop. |
| 95 { | 95 { |
| 96 AutoLock lock(list_lock_); | 96 base::AutoLock lock(list_lock_); |
| 97 if (observer_lists_.find(loop) == observer_lists_.end()) | 97 if (observer_lists_.find(loop) == observer_lists_.end()) |
| 98 observer_lists_[loop] = new ObserverList<ObserverType>(type_); | 98 observer_lists_[loop] = new ObserverList<ObserverType>(type_); |
| 99 list = observer_lists_[loop]; | 99 list = observer_lists_[loop]; |
| 100 } | 100 } |
| 101 list->AddObserver(obs); | 101 list->AddObserver(obs); |
| 102 } | 102 } |
| 103 | 103 |
| 104 // Remove an observer from the list. | 104 // Remove an observer from the list. |
| 105 // If there are pending notifications in-transit to the observer, they will | 105 // If there are pending notifications in-transit to the observer, they will |
| 106 // be aborted. | 106 // be aborted. |
| 107 // RemoveObserver MUST be called from the same thread which called | 107 // RemoveObserver MUST be called from the same thread which called |
| 108 // AddObserver. | 108 // AddObserver. |
| 109 void RemoveObserver(ObserverType* obs) { | 109 void RemoveObserver(ObserverType* obs) { |
| 110 ObserverList<ObserverType>* list = NULL; | 110 ObserverList<ObserverType>* list = NULL; |
| 111 MessageLoop* loop = MessageLoop::current(); | 111 MessageLoop* loop = MessageLoop::current(); |
| 112 if (!loop) | 112 if (!loop) |
| 113 return; // On shutdown, it is possible that current() is already null. | 113 return; // On shutdown, it is possible that current() is already null. |
| 114 { | 114 { |
| 115 AutoLock lock(list_lock_); | 115 base::AutoLock lock(list_lock_); |
| 116 list = observer_lists_[loop]; | 116 list = observer_lists_[loop]; |
| 117 if (!list) { | 117 if (!list) { |
| 118 NOTREACHED() << "RemoveObserver called on for unknown thread"; | 118 NOTREACHED() << "RemoveObserver called on for unknown thread"; |
| 119 return; | 119 return; |
| 120 } | 120 } |
| 121 | 121 |
| 122 // If we're about to remove the last observer from the list, | 122 // If we're about to remove the last observer from the list, |
| 123 // then we can remove this observer_list entirely. | 123 // then we can remove this observer_list entirely. |
| 124 if (list->size() == 1) | 124 if (list->size() == 1) |
| 125 observer_lists_.erase(loop); | 125 observer_lists_.erase(loop); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 158 |
| 159 ~ObserverListThreadSafe() { | 159 ~ObserverListThreadSafe() { |
| 160 typename ObserversListMap::const_iterator it; | 160 typename ObserversListMap::const_iterator it; |
| 161 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) | 161 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) |
| 162 delete (*it).second; | 162 delete (*it).second; |
| 163 observer_lists_.clear(); | 163 observer_lists_.clear(); |
| 164 } | 164 } |
| 165 | 165 |
| 166 template <class Method, class Params> | 166 template <class Method, class Params> |
| 167 void Notify(const UnboundMethod<ObserverType, Method, Params>& method) { | 167 void Notify(const UnboundMethod<ObserverType, Method, Params>& method) { |
| 168 AutoLock lock(list_lock_); | 168 base::AutoLock lock(list_lock_); |
| 169 typename ObserversListMap::iterator it; | 169 typename ObserversListMap::iterator it; |
| 170 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) { | 170 for (it = observer_lists_.begin(); it != observer_lists_.end(); ++it) { |
| 171 MessageLoop* loop = (*it).first; | 171 MessageLoop* loop = (*it).first; |
| 172 ObserverList<ObserverType>* list = (*it).second; | 172 ObserverList<ObserverType>* list = (*it).second; |
| 173 loop->PostTask( | 173 loop->PostTask( |
| 174 FROM_HERE, | 174 FROM_HERE, |
| 175 NewRunnableMethod(this, | 175 NewRunnableMethod(this, |
| 176 &ObserverListThreadSafe<ObserverType>:: | 176 &ObserverListThreadSafe<ObserverType>:: |
| 177 template NotifyWrapper<Method, Params>, list, method)); | 177 template NotifyWrapper<Method, Params>, list, method)); |
| 178 } | 178 } |
| 179 } | 179 } |
| 180 | 180 |
| 181 // Wrapper which is called to fire the notifications for each thread's | 181 // Wrapper which is called to fire the notifications for each thread's |
| 182 // ObserverList. This function MUST be called on the thread which owns | 182 // ObserverList. This function MUST be called on the thread which owns |
| 183 // the unsafe ObserverList. | 183 // the unsafe ObserverList. |
| 184 template <class Method, class Params> | 184 template <class Method, class Params> |
| 185 void NotifyWrapper(ObserverList<ObserverType>* list, | 185 void NotifyWrapper(ObserverList<ObserverType>* list, |
| 186 const UnboundMethod<ObserverType, Method, Params>& method) { | 186 const UnboundMethod<ObserverType, Method, Params>& method) { |
| 187 | 187 |
| 188 // Check that this list still needs notifications. | 188 // Check that this list still needs notifications. |
| 189 { | 189 { |
| 190 AutoLock lock(list_lock_); | 190 base::AutoLock lock(list_lock_); |
| 191 typename ObserversListMap::iterator it = | 191 typename ObserversListMap::iterator it = |
| 192 observer_lists_.find(MessageLoop::current()); | 192 observer_lists_.find(MessageLoop::current()); |
| 193 | 193 |
| 194 // The ObserverList could have been removed already. In fact, it could | 194 // The ObserverList could have been removed already. In fact, it could |
| 195 // have been removed and then re-added! If the master list's loop | 195 // have been removed and then re-added! If the master list's loop |
| 196 // does not match this one, then we do not need to finish this | 196 // does not match this one, then we do not need to finish this |
| 197 // notification. | 197 // notification. |
| 198 if (it == observer_lists_.end() || it->second != list) | 198 if (it == observer_lists_.end() || it->second != list) |
| 199 return; | 199 return; |
| 200 } | 200 } |
| 201 | 201 |
| 202 { | 202 { |
| 203 typename ObserverList<ObserverType>::Iterator it(*list); | 203 typename ObserverList<ObserverType>::Iterator it(*list); |
| 204 ObserverType* obs; | 204 ObserverType* obs; |
| 205 while ((obs = it.GetNext()) != NULL) | 205 while ((obs = it.GetNext()) != NULL) |
| 206 method.Run(obs); | 206 method.Run(obs); |
| 207 } | 207 } |
| 208 | 208 |
| 209 // If there are no more observers on the list, we can now delete it. | 209 // If there are no more observers on the list, we can now delete it. |
| 210 if (list->size() == 0) { | 210 if (list->size() == 0) { |
| 211 { | 211 { |
| 212 AutoLock lock(list_lock_); | 212 base::AutoLock lock(list_lock_); |
| 213 // Remove |list| if it's not already removed. | 213 // Remove |list| if it's not already removed. |
| 214 // This can happen if multiple observers got removed in a notification. | 214 // This can happen if multiple observers got removed in a notification. |
| 215 // See http://crbug.com/55725. | 215 // See http://crbug.com/55725. |
| 216 typename ObserversListMap::iterator it = | 216 typename ObserversListMap::iterator it = |
| 217 observer_lists_.find(MessageLoop::current()); | 217 observer_lists_.find(MessageLoop::current()); |
| 218 if (it != observer_lists_.end() && it->second == list) | 218 if (it != observer_lists_.end() && it->second == list) |
| 219 observer_lists_.erase(it); | 219 observer_lists_.erase(it); |
| 220 } | 220 } |
| 221 delete list; | 221 delete list; |
| 222 } | 222 } |
| 223 } | 223 } |
| 224 | 224 |
| 225 typedef std::map<MessageLoop*, ObserverList<ObserverType>*> ObserversListMap; | 225 typedef std::map<MessageLoop*, ObserverList<ObserverType>*> ObserversListMap; |
| 226 | 226 |
| 227 // These are marked mutable to facilitate having NotifyAll be const. | 227 // These are marked mutable to facilitate having NotifyAll be const. |
| 228 Lock list_lock_; // Protects the observer_lists_. | 228 base::Lock list_lock_; // Protects the observer_lists_. |
| 229 ObserversListMap observer_lists_; | 229 ObserversListMap observer_lists_; |
| 230 const NotificationType type_; | 230 const NotificationType type_; |
| 231 | 231 |
| 232 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); | 232 DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe); |
| 233 }; | 233 }; |
| 234 | 234 |
| 235 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ | 235 #endif // BASE_OBSERVER_LIST_THREADSAFE_H_ |
| OLD | NEW |