OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ios/web/web_thread_impl.h" | 5 #include "ios/web/web_thread_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 } | 41 } |
42 | 42 |
43 // An implementation of SingleThreadTaskRunner to be used in conjunction | 43 // An implementation of SingleThreadTaskRunner to be used in conjunction |
44 // with WebThread. | 44 // with WebThread. |
45 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { | 45 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { |
46 public: | 46 public: |
47 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} | 47 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} |
48 | 48 |
49 // SingleThreadTaskRunner implementation. | 49 // SingleThreadTaskRunner implementation. |
50 bool PostDelayedTask(const tracked_objects::Location& from_here, | 50 bool PostDelayedTask(const tracked_objects::Location& from_here, |
51 const base::Closure& task, | 51 base::OnceClosure task, |
52 base::TimeDelta delay) override { | 52 base::TimeDelta delay) override { |
53 return WebThread::PostDelayedTask(id_, from_here, task, delay); | 53 return WebThread::PostDelayedTask(id_, from_here, std::move(task), delay); |
54 } | 54 } |
55 | 55 |
56 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 56 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
57 const base::Closure& task, | 57 base::OnceClosure task, |
58 base::TimeDelta delay) override { | 58 base::TimeDelta delay) override { |
59 return WebThread::PostNonNestableDelayedTask(id_, from_here, task, delay); | 59 return WebThread::PostNonNestableDelayedTask(id_, from_here, |
| 60 std::move(task), delay); |
60 } | 61 } |
61 | 62 |
62 bool RunsTasksOnCurrentThread() const override { | 63 bool RunsTasksOnCurrentThread() const override { |
63 return WebThread::CurrentlyOn(id_); | 64 return WebThread::CurrentlyOn(id_); |
64 } | 65 } |
65 | 66 |
66 protected: | 67 protected: |
67 ~WebThreadTaskRunner() override {} | 68 ~WebThreadTaskRunner() override {} |
68 | 69 |
69 private: | 70 private: |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { | 283 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { |
283 DCHECK(!globals.threads[i]) | 284 DCHECK(!globals.threads[i]) |
284 << "Threads must be listed in the reverse order that they die"; | 285 << "Threads must be listed in the reverse order that they die"; |
285 } | 286 } |
286 #endif | 287 #endif |
287 } | 288 } |
288 | 289 |
289 // static | 290 // static |
290 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, | 291 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, |
291 const tracked_objects::Location& from_here, | 292 const tracked_objects::Location& from_here, |
292 const base::Closure& task, | 293 base::OnceClosure task, |
293 base::TimeDelta delay, | 294 base::TimeDelta delay, |
294 bool nestable) { | 295 bool nestable) { |
295 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 296 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
296 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in | 297 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in |
297 // order of lifetime. So no need to lock if we know that the target thread | 298 // order of lifetime. So no need to lock if we know that the target thread |
298 // outlives current thread. | 299 // outlives current thread. |
299 // Note: since the array is so small, ok to loop instead of creating a map, | 300 // Note: since the array is so small, ok to loop instead of creating a map, |
300 // which would require a lock because std::map isn't thread safe, defeating | 301 // which would require a lock because std::map isn't thread safe, defeating |
301 // the whole purpose of this optimization. | 302 // the whole purpose of this optimization. |
302 WebThread::ID current_thread = ID_COUNT; | 303 WebThread::ID current_thread = ID_COUNT; |
303 bool target_thread_outlives_current = | 304 bool target_thread_outlives_current = |
304 GetCurrentThreadIdentifier(¤t_thread) && | 305 GetCurrentThreadIdentifier(¤t_thread) && |
305 current_thread >= identifier; | 306 current_thread >= identifier; |
306 | 307 |
307 WebThreadGlobals& globals = g_globals.Get(); | 308 WebThreadGlobals& globals = g_globals.Get(); |
308 if (!target_thread_outlives_current) | 309 if (!target_thread_outlives_current) |
309 globals.lock.Acquire(); | 310 globals.lock.Acquire(); |
310 | 311 |
311 base::MessageLoop* message_loop = | 312 base::MessageLoop* message_loop = |
312 globals.threads[identifier] ? globals.threads[identifier]->message_loop() | 313 globals.threads[identifier] ? globals.threads[identifier]->message_loop() |
313 : nullptr; | 314 : nullptr; |
314 if (message_loop) { | 315 if (message_loop) { |
315 if (nestable) { | 316 if (nestable) { |
316 message_loop->task_runner()->PostDelayedTask(from_here, task, delay); | 317 message_loop->task_runner()->PostDelayedTask(from_here, std::move(task), |
| 318 delay); |
317 } else { | 319 } else { |
318 message_loop->task_runner()->PostNonNestableDelayedTask(from_here, task, | 320 message_loop->task_runner()->PostNonNestableDelayedTask( |
319 delay); | 321 from_here, std::move(task), delay); |
320 } | 322 } |
321 } | 323 } |
322 | 324 |
323 if (!target_thread_outlives_current) | 325 if (!target_thread_outlives_current) |
324 globals.lock.Release(); | 326 globals.lock.Release(); |
325 | 327 |
326 return !!message_loop; | 328 return !!message_loop; |
327 } | 329 } |
328 | 330 |
329 // static | 331 // static |
330 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, | 332 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, |
331 const base::Closure& task) { | 333 base::OnceClosure task) { |
332 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task); | 334 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, |
| 335 std::move(task)); |
333 } | 336 } |
334 | 337 |
335 // static | 338 // static |
336 bool WebThread::PostBlockingPoolTaskAndReply( | 339 bool WebThread::PostBlockingPoolTaskAndReply( |
337 const tracked_objects::Location& from_here, | 340 const tracked_objects::Location& from_here, |
338 const base::Closure& task, | 341 base::OnceClosure task, |
339 const base::Closure& reply) { | 342 base::OnceClosure reply) { |
340 return g_globals.Get().blocking_pool->PostTaskAndReply(from_here, task, | 343 return g_globals.Get().blocking_pool->PostTaskAndReply( |
341 reply); | 344 from_here, std::move(task), std::move(reply)); |
342 } | 345 } |
343 | 346 |
344 // static | 347 // static |
345 bool WebThread::PostBlockingPoolSequencedTask( | 348 bool WebThread::PostBlockingPoolSequencedTask( |
346 const std::string& sequence_token_name, | 349 const std::string& sequence_token_name, |
347 const tracked_objects::Location& from_here, | 350 const tracked_objects::Location& from_here, |
348 const base::Closure& task) { | 351 base::OnceClosure task) { |
349 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( | 352 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( |
350 sequence_token_name, from_here, task); | 353 sequence_token_name, from_here, std::move(task)); |
351 } | 354 } |
352 | 355 |
353 // static | 356 // static |
354 base::SequencedWorkerPool* WebThread::GetBlockingPool() { | 357 base::SequencedWorkerPool* WebThread::GetBlockingPool() { |
355 return g_globals.Get().blocking_pool.get(); | 358 return g_globals.Get().blocking_pool.get(); |
356 } | 359 } |
357 | 360 |
358 // static | 361 // static |
359 bool WebThread::IsThreadInitialized(ID identifier) { | 362 bool WebThread::IsThreadInitialized(ID identifier) { |
360 if (g_globals == nullptr) | 363 if (g_globals == nullptr) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 WebThreadGlobals& globals = g_globals.Get(); | 406 WebThreadGlobals& globals = g_globals.Get(); |
404 base::AutoLock lock(globals.lock); | 407 base::AutoLock lock(globals.lock); |
405 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 408 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
406 return globals.threads[identifier] && | 409 return globals.threads[identifier] && |
407 globals.threads[identifier]->message_loop(); | 410 globals.threads[identifier]->message_loop(); |
408 } | 411 } |
409 | 412 |
410 // static | 413 // static |
411 bool WebThread::PostTask(ID identifier, | 414 bool WebThread::PostTask(ID identifier, |
412 const tracked_objects::Location& from_here, | 415 const tracked_objects::Location& from_here, |
413 const base::Closure& task) { | 416 base::OnceClosure task) { |
414 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 417 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
415 base::TimeDelta(), true); | 418 base::TimeDelta(), true); |
416 } | 419 } |
417 | 420 |
418 // static | 421 // static |
419 bool WebThread::PostDelayedTask(ID identifier, | 422 bool WebThread::PostDelayedTask(ID identifier, |
420 const tracked_objects::Location& from_here, | 423 const tracked_objects::Location& from_here, |
421 const base::Closure& task, | 424 base::OnceClosure task, |
422 base::TimeDelta delay) { | 425 base::TimeDelta delay) { |
423 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 426 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
424 true); | 427 delay, true); |
425 } | 428 } |
426 | 429 |
427 // static | 430 // static |
428 bool WebThread::PostNonNestableTask(ID identifier, | 431 bool WebThread::PostNonNestableTask(ID identifier, |
429 const tracked_objects::Location& from_here, | 432 const tracked_objects::Location& from_here, |
430 const base::Closure& task) { | 433 base::OnceClosure task) { |
431 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 434 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
432 base::TimeDelta(), false); | 435 base::TimeDelta(), false); |
433 } | 436 } |
434 | 437 |
435 // static | 438 // static |
436 bool WebThread::PostNonNestableDelayedTask( | 439 bool WebThread::PostNonNestableDelayedTask( |
437 ID identifier, | 440 ID identifier, |
438 const tracked_objects::Location& from_here, | 441 const tracked_objects::Location& from_here, |
439 const base::Closure& task, | 442 base::OnceClosure task, |
440 base::TimeDelta delay) { | 443 base::TimeDelta delay) { |
441 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 444 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
442 false); | 445 delay, false); |
443 } | 446 } |
444 | 447 |
445 // static | 448 // static |
446 bool WebThread::PostTaskAndReply(ID identifier, | 449 bool WebThread::PostTaskAndReply(ID identifier, |
447 const tracked_objects::Location& from_here, | 450 const tracked_objects::Location& from_here, |
448 const base::Closure& task, | 451 base::OnceClosure task, |
449 const base::Closure& reply) { | 452 base::OnceClosure reply) { |
450 return GetTaskRunnerForThread(identifier) | 453 return GetTaskRunnerForThread(identifier) |
451 ->PostTaskAndReply(from_here, task, reply); | 454 ->PostTaskAndReply(from_here, std::move(task), std::move(reply)); |
452 } | 455 } |
453 | 456 |
454 // static | 457 // static |
455 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { | 458 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { |
456 if (g_globals == nullptr) | 459 if (g_globals == nullptr) |
457 return false; | 460 return false; |
458 | 461 |
459 // This shouldn't use MessageLoop::current() since it uses LazyInstance which | 462 // This shouldn't use MessageLoop::current() since it uses LazyInstance which |
460 // may be deleted by ~AtExitManager when a WorkerPool thread calls this | 463 // may be deleted by ~AtExitManager when a WorkerPool thread calls this |
461 // function. | 464 // function. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 AtomicWord* storage = | 503 AtomicWord* storage = |
501 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); | 504 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); |
502 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 505 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
503 storage, reinterpret_cast<AtomicWord>(delegate)); | 506 storage, reinterpret_cast<AtomicWord>(delegate)); |
504 | 507 |
505 // This catches registration when previously registered. | 508 // This catches registration when previously registered. |
506 DCHECK(!delegate || !old_pointer); | 509 DCHECK(!delegate || !old_pointer); |
507 } | 510 } |
508 | 511 |
509 } // namespace web | 512 } // namespace web |
OLD | NEW |