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 #include "content/browser/browser_thread_impl.h" | 5 #include "content/browser/browser_thread_impl.h" |
6 | 6 |
7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 "Threads must be listed in the reverse order that they die"; | 134 "Threads must be listed in the reverse order that they die"; |
135 } | 135 } |
136 #endif | 136 #endif |
137 } | 137 } |
138 | 138 |
139 // static | 139 // static |
140 bool BrowserThreadImpl::PostTaskHelper( | 140 bool BrowserThreadImpl::PostTaskHelper( |
141 BrowserThread::ID identifier, | 141 BrowserThread::ID identifier, |
142 const tracked_objects::Location& from_here, | 142 const tracked_objects::Location& from_here, |
143 const base::Closure& task, | 143 const base::Closure& task, |
144 int64 delay_ms, | 144 base::TimeDelta delay, |
145 bool nestable) { | 145 bool nestable) { |
146 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 146 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
147 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in | 147 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in |
148 // order of lifetime. So no need to lock if we know that the other thread | 148 // order of lifetime. So no need to lock if we know that the other thread |
149 // outlives this one. | 149 // outlives this one. |
150 // Note: since the array is so small, ok to loop instead of creating a map, | 150 // Note: since the array is so small, ok to loop instead of creating a map, |
151 // which would require a lock because std::map isn't thread safe, defeating | 151 // which would require a lock because std::map isn't thread safe, defeating |
152 // the whole purpose of this optimization. | 152 // the whole purpose of this optimization. |
153 BrowserThread::ID current_thread; | 153 BrowserThread::ID current_thread; |
154 bool guaranteed_to_outlive_target_thread = | 154 bool guaranteed_to_outlive_target_thread = |
155 GetCurrentThreadIdentifier(¤t_thread) && | 155 GetCurrentThreadIdentifier(¤t_thread) && |
156 current_thread <= identifier; | 156 current_thread <= identifier; |
157 | 157 |
158 BrowserThreadGlobals& globals = g_globals.Get(); | 158 BrowserThreadGlobals& globals = g_globals.Get(); |
159 if (!guaranteed_to_outlive_target_thread) | 159 if (!guaranteed_to_outlive_target_thread) |
160 globals.lock.Acquire(); | 160 globals.lock.Acquire(); |
161 | 161 |
162 MessageLoop* message_loop = globals.threads[identifier] ? | 162 MessageLoop* message_loop = globals.threads[identifier] ? |
163 globals.threads[identifier]->message_loop() : NULL; | 163 globals.threads[identifier]->message_loop() : NULL; |
164 if (message_loop) { | 164 if (message_loop) { |
165 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); | |
166 if (nestable) { | 165 if (nestable) { |
167 message_loop->PostDelayedTask(from_here, task, delay); | 166 message_loop->PostDelayedTask(from_here, task, delay); |
168 } else { | 167 } else { |
169 message_loop->PostNonNestableDelayedTask(from_here, task, delay); | 168 message_loop->PostNonNestableDelayedTask(from_here, task, delay); |
170 } | 169 } |
171 } | 170 } |
172 | 171 |
173 if (!guaranteed_to_outlive_target_thread) | 172 if (!guaranteed_to_outlive_target_thread) |
174 globals.lock.Release(); | 173 globals.lock.Release(); |
175 | 174 |
176 return !!message_loop; | 175 return !!message_loop; |
177 } | 176 } |
178 | 177 |
179 // An implementation of MessageLoopProxy to be used in conjunction | 178 // An implementation of MessageLoopProxy to be used in conjunction |
180 // with BrowserThread. | 179 // with BrowserThread. |
181 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { | 180 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { |
182 public: | 181 public: |
183 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) | 182 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) |
184 : id_(identifier) { | 183 : id_(identifier) { |
185 } | 184 } |
186 | 185 |
187 // MessageLoopProxy implementation. | 186 // MessageLoopProxy implementation. |
188 virtual bool PostDelayedTask( | 187 virtual bool PostDelayedTask( |
189 const tracked_objects::Location& from_here, | 188 const tracked_objects::Location& from_here, |
190 const base::Closure& task, int64 delay_ms) OVERRIDE{ | 189 const base::Closure& task, int64 delay_ms) OVERRIDE { |
191 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms); | 190 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms); |
192 } | 191 } |
| 192 virtual bool PostDelayedTask( |
| 193 const tracked_objects::Location& from_here, |
| 194 const base::Closure& task, base::TimeDelta delay) OVERRIDE { |
| 195 return BrowserThread::PostDelayedTask(id_, from_here, task, delay); |
| 196 } |
193 | 197 |
194 virtual bool PostNonNestableDelayedTask( | 198 virtual bool PostNonNestableDelayedTask( |
195 const tracked_objects::Location& from_here, | 199 const tracked_objects::Location& from_here, |
196 const base::Closure& task, | 200 const base::Closure& task, |
197 int64 delay_ms) OVERRIDE { | 201 int64 delay_ms) OVERRIDE { |
198 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, | 202 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, |
199 delay_ms); | 203 delay_ms); |
200 } | 204 } |
| 205 virtual bool PostNonNestableDelayedTask( |
| 206 const tracked_objects::Location& from_here, |
| 207 const base::Closure& task, |
| 208 base::TimeDelta delay) OVERRIDE { |
| 209 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, |
| 210 delay); |
| 211 } |
201 | 212 |
202 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { | 213 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { |
203 return BrowserThread::CurrentlyOn(id_); | 214 return BrowserThread::CurrentlyOn(id_); |
204 } | 215 } |
205 | 216 |
206 private: | 217 private: |
207 BrowserThread::ID id_; | 218 BrowserThread::ID id_; |
208 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); | 219 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); |
209 }; | 220 }; |
210 | 221 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 270 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
260 return globals.threads[identifier] && | 271 return globals.threads[identifier] && |
261 globals.threads[identifier]->message_loop(); | 272 globals.threads[identifier]->message_loop(); |
262 } | 273 } |
263 | 274 |
264 // static | 275 // static |
265 bool BrowserThread::PostTask(ID identifier, | 276 bool BrowserThread::PostTask(ID identifier, |
266 const tracked_objects::Location& from_here, | 277 const tracked_objects::Location& from_here, |
267 const base::Closure& task) { | 278 const base::Closure& task) { |
268 return BrowserThreadImpl::PostTaskHelper( | 279 return BrowserThreadImpl::PostTaskHelper( |
269 identifier, from_here, task, 0, true); | 280 identifier, from_here, task, base::TimeDelta(), true); |
270 } | 281 } |
271 | 282 |
272 // static | 283 // static |
273 bool BrowserThread::PostDelayedTask(ID identifier, | 284 bool BrowserThread::PostDelayedTask(ID identifier, |
274 const tracked_objects::Location& from_here, | 285 const tracked_objects::Location& from_here, |
275 const base::Closure& task, | 286 const base::Closure& task, |
276 int64 delay_ms) { | 287 int64 delay_ms) { |
277 return BrowserThreadImpl::PostTaskHelper( | 288 return BrowserThreadImpl::PostTaskHelper( |
278 identifier, from_here, task, delay_ms, true); | 289 identifier, |
| 290 from_here, |
| 291 task, |
| 292 base::TimeDelta::FromMilliseconds(delay_ms), |
| 293 true); |
279 } | 294 } |
280 | 295 |
281 // static | 296 // static |
| 297 bool BrowserThread::PostDelayedTask(ID identifier, |
| 298 const tracked_objects::Location& from_here, |
| 299 const base::Closure& task, |
| 300 base::TimeDelta delay) { |
| 301 return BrowserThreadImpl::PostTaskHelper( |
| 302 identifier, from_here, task, delay, true); |
| 303 } |
| 304 |
| 305 // static |
282 bool BrowserThread::PostNonNestableTask( | 306 bool BrowserThread::PostNonNestableTask( |
283 ID identifier, | 307 ID identifier, |
284 const tracked_objects::Location& from_here, | 308 const tracked_objects::Location& from_here, |
285 const base::Closure& task) { | 309 const base::Closure& task) { |
286 return BrowserThreadImpl::PostTaskHelper( | 310 return BrowserThreadImpl::PostTaskHelper( |
287 identifier, from_here, task, 0, false); | 311 identifier, from_here, task, base::TimeDelta(), false); |
288 } | 312 } |
289 | 313 |
290 // static | 314 // static |
291 bool BrowserThread::PostNonNestableDelayedTask( | 315 bool BrowserThread::PostNonNestableDelayedTask( |
292 ID identifier, | 316 ID identifier, |
293 const tracked_objects::Location& from_here, | 317 const tracked_objects::Location& from_here, |
294 const base::Closure& task, | 318 const base::Closure& task, |
295 int64 delay_ms) { | 319 int64 delay_ms) { |
296 return BrowserThreadImpl::PostTaskHelper( | 320 return BrowserThreadImpl::PostTaskHelper( |
297 identifier, from_here, task, delay_ms, false); | 321 identifier, |
| 322 from_here, |
| 323 task, |
| 324 base::TimeDelta::FromMilliseconds(delay_ms), |
| 325 false); |
298 } | 326 } |
299 | 327 |
300 // static | 328 // static |
| 329 bool BrowserThread::PostNonNestableDelayedTask( |
| 330 ID identifier, |
| 331 const tracked_objects::Location& from_here, |
| 332 const base::Closure& task, |
| 333 base::TimeDelta delay) { |
| 334 return BrowserThreadImpl::PostTaskHelper( |
| 335 identifier, from_here, task, delay, false); |
| 336 } |
| 337 |
| 338 // static |
301 bool BrowserThread::PostTaskAndReply( | 339 bool BrowserThread::PostTaskAndReply( |
302 ID identifier, | 340 ID identifier, |
303 const tracked_objects::Location& from_here, | 341 const tracked_objects::Location& from_here, |
304 const base::Closure& task, | 342 const base::Closure& task, |
305 const base::Closure& reply) { | 343 const base::Closure& reply) { |
306 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here, | 344 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here, |
307 task, | 345 task, |
308 reply); | 346 reply); |
309 } | 347 } |
310 | 348 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 AtomicWord* storage = reinterpret_cast<AtomicWord*>( | 392 AtomicWord* storage = reinterpret_cast<AtomicWord*>( |
355 &globals.thread_delegates[identifier]); | 393 &globals.thread_delegates[identifier]); |
356 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 394 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
357 storage, reinterpret_cast<AtomicWord>(delegate)); | 395 storage, reinterpret_cast<AtomicWord>(delegate)); |
358 | 396 |
359 // This catches registration when previously registered. | 397 // This catches registration when previously registered. |
360 DCHECK(!delegate || !old_pointer); | 398 DCHECK(!delegate || !old_pointer); |
361 } | 399 } |
362 | 400 |
363 } // namespace content | 401 } // namespace content |
OLD | NEW |