Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: base/threading/sequenced_worker_pool.cc

Issue 10913242: Trace PostTasks from post to run (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: minor tweak Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "base/threading/sequenced_worker_pool.h" 5 #include "base/threading/sequenced_worker_pool.h"
6 6
7 #include <list> 7 #include <list>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/atomicops.h" 13 #include "base/atomicops.h"
14 #include "base/callback.h" 14 #include "base/callback.h"
15 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
16 #include "base/critical_closure.h" 16 #include "base/critical_closure.h"
17 #include "base/debug/trace_event.h"
17 #include "base/logging.h" 18 #include "base/logging.h"
18 #include "base/memory/linked_ptr.h" 19 #include "base/memory/linked_ptr.h"
19 #include "base/message_loop_proxy.h" 20 #include "base/message_loop_proxy.h"
20 #include "base/metrics/histogram.h" 21 #include "base/metrics/histogram.h"
21 #include "base/stl_util.h" 22 #include "base/stl_util.h"
22 #include "base/stringprintf.h" 23 #include "base/stringprintf.h"
23 #include "base/synchronization/condition_variable.h" 24 #include "base/synchronization/condition_variable.h"
24 #include "base/synchronization/lock.h" 25 #include "base/synchronization/lock.h"
25 #include "base/threading/platform_thread.h" 26 #include "base/threading/platform_thread.h"
26 #include "base/threading/simple_thread.h" 27 #include "base/threading/simple_thread.h"
27 #include "base/threading/thread_restrictions.h" 28 #include "base/threading/thread_restrictions.h"
28 #include "base/time.h" 29 #include "base/time.h"
29 #include "base/tracked_objects.h" 30 #include "base/tracked_objects.h"
30 31
31 #if defined(OS_MACOSX) 32 #if defined(OS_MACOSX)
32 #include "base/mac/scoped_nsautorelease_pool.h" 33 #include "base/mac/scoped_nsautorelease_pool.h"
33 #endif 34 #endif
34 35
35 namespace base { 36 namespace base {
36 37
37 namespace { 38 namespace {
38 39
39 struct SequencedTask : public TrackingInfo { 40 struct SequencedTask : public TrackingInfo {
40 SequencedTask() 41 SequencedTask()
41 : sequence_token_id(0), 42 : sequence_token_id(0),
43 trace_id(0),
42 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} 44 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {}
43 45
44 explicit SequencedTask(const tracked_objects::Location& from_here) 46 explicit SequencedTask(const tracked_objects::Location& from_here)
45 : base::TrackingInfo(from_here, TimeTicks()), 47 : base::TrackingInfo(from_here, TimeTicks()),
46 sequence_token_id(0), 48 sequence_token_id(0),
49 trace_id(0),
47 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} 50 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {}
48 51
49 ~SequencedTask() {} 52 ~SequencedTask() {}
50 53
51 int sequence_token_id; 54 int sequence_token_id;
55 int trace_id;
52 SequencedWorkerPool::WorkerShutdown shutdown_behavior; 56 SequencedWorkerPool::WorkerShutdown shutdown_behavior;
53 tracked_objects::Location posted_from; 57 tracked_objects::Location posted_from;
54 Closure task; 58 Closure task;
55 }; 59 };
56 60
57 // SequencedWorkerPoolTaskRunner --------------------------------------------- 61 // SequencedWorkerPoolTaskRunner ---------------------------------------------
58 // A TaskRunner which posts tasks to a SequencedWorkerPool with a 62 // A TaskRunner which posts tasks to a SequencedWorkerPool with a
59 // fixed ShutdownBehavior. 63 // fixed ShutdownBehavior.
60 // 64 //
61 // Note that this class is RefCountedThreadSafe (inherited from TaskRunner). 65 // Note that this class is RefCountedThreadSafe (inherited from TaskRunner).
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 TimeDelta delay) { 205 TimeDelta delay) {
202 // TODO(francoisk777@gmail.com): Change the following two statements once 206 // TODO(francoisk777@gmail.com): Change the following two statements once
203 // SequencedWorkerPool supports non-zero delays. 207 // SequencedWorkerPool supports non-zero delays.
204 DCHECK_EQ(delay.InMillisecondsRoundedUp(), 0) 208 DCHECK_EQ(delay.InMillisecondsRoundedUp(), 0)
205 << "SequencedWorkerPoolSequencedTaskRunner does not yet support non-zero" 209 << "SequencedWorkerPoolSequencedTaskRunner does not yet support non-zero"
206 " delays"; 210 " delays";
207 return pool_->PostSequencedWorkerTaskWithShutdownBehavior( 211 return pool_->PostSequencedWorkerTaskWithShutdownBehavior(
208 token_, from_here, task, shutdown_behavior_); 212 token_, from_here, task, shutdown_behavior_);
209 } 213 }
210 214
215 // Create a process-wide unique ID to represent this task in trace events. This
216 // will be mangled with a Process ID hash to reduce the likelyhood of colliding
217 // with MessageLoop pointers on other processes.
218 uint64 GetTaskTraceID(const SequencedTask& task,
219 void* pool) {
220 return (static_cast<uint64>(task.trace_id) << 32) |
221 static_cast<uint64>(reinterpret_cast<intptr_t>(pool));
222 }
223
211 } // namespace 224 } // namespace
212 225
213 // Worker --------------------------------------------------------------------- 226 // Worker ---------------------------------------------------------------------
214 227
215 class SequencedWorkerPool::Worker : public SimpleThread { 228 class SequencedWorkerPool::Worker : public SimpleThread {
216 public: 229 public:
217 // Hold a (cyclic) ref to |worker_pool|, since we want to keep it 230 // Hold a (cyclic) ref to |worker_pool|, since we want to keep it
218 // around as long as we are running. 231 // around as long as we are running.
219 Worker(const scoped_refptr<SequencedWorkerPool>& worker_pool, 232 Worker(const scoped_refptr<SequencedWorkerPool>& worker_pool,
220 int thread_number, 233 int thread_number,
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 std::list<SequencedTask> pending_tasks_; 402 std::list<SequencedTask> pending_tasks_;
390 size_t pending_task_count_; 403 size_t pending_task_count_;
391 404
392 // Number of tasks in the pending_tasks_ list that are marked as blocking 405 // Number of tasks in the pending_tasks_ list that are marked as blocking
393 // shutdown. 406 // shutdown.
394 size_t blocking_shutdown_pending_task_count_; 407 size_t blocking_shutdown_pending_task_count_;
395 408
396 // Lists all sequence tokens currently executing. 409 // Lists all sequence tokens currently executing.
397 std::set<int> current_sequences_; 410 std::set<int> current_sequences_;
398 411
412 // An ID for each posted task to distinguish the task from others in traces.
413 int trace_id_;
414
399 // Set when Shutdown is called and no further tasks should be 415 // Set when Shutdown is called and no further tasks should be
400 // allowed, though we may still be running existing tasks. 416 // allowed, though we may still be running existing tasks.
401 bool shutdown_called_; 417 bool shutdown_called_;
402 418
403 TestingObserver* const testing_observer_; 419 TestingObserver* const testing_observer_;
404 420
405 DISALLOW_COPY_AND_ASSIGN(Inner); 421 DISALLOW_COPY_AND_ASSIGN(Inner);
406 }; 422 };
407 423
408 // Worker definitions --------------------------------------------------------- 424 // Worker definitions ---------------------------------------------------------
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 has_work_cv_(&lock_), 460 has_work_cv_(&lock_),
445 is_idle_cv_(&lock_), 461 is_idle_cv_(&lock_),
446 can_shutdown_cv_(&lock_), 462 can_shutdown_cv_(&lock_),
447 max_threads_(max_threads), 463 max_threads_(max_threads),
448 thread_name_prefix_(thread_name_prefix), 464 thread_name_prefix_(thread_name_prefix),
449 thread_being_created_(false), 465 thread_being_created_(false),
450 waiting_thread_count_(0), 466 waiting_thread_count_(0),
451 blocking_shutdown_thread_count_(0), 467 blocking_shutdown_thread_count_(0),
452 pending_task_count_(0), 468 pending_task_count_(0),
453 blocking_shutdown_pending_task_count_(0), 469 blocking_shutdown_pending_task_count_(0),
470 trace_id_(0),
454 shutdown_called_(false), 471 shutdown_called_(false),
455 testing_observer_(observer) {} 472 testing_observer_(observer) {}
456 473
457 SequencedWorkerPool::Inner::~Inner() { 474 SequencedWorkerPool::Inner::~Inner() {
458 // You must call Shutdown() before destroying the pool. 475 // You must call Shutdown() before destroying the pool.
459 DCHECK(shutdown_called_); 476 DCHECK(shutdown_called_);
460 477
461 // Need to explicitly join with the threads before they're destroyed or else 478 // Need to explicitly join with the threads before they're destroyed or else
462 // they will be running when our object is half torn down. 479 // they will be running when our object is half torn down.
463 for (ThreadMap::iterator it = threads_.begin(); it != threads_.end(); ++it) 480 for (ThreadMap::iterator it = threads_.begin(); it != threads_.end(); ++it)
(...skipping 30 matching lines...) Expand all
494 sequenced.task = 511 sequenced.task =
495 shutdown_behavior == BLOCK_SHUTDOWN ? 512 shutdown_behavior == BLOCK_SHUTDOWN ?
496 base::MakeCriticalClosure(task) : task; 513 base::MakeCriticalClosure(task) : task;
497 514
498 int create_thread_id = 0; 515 int create_thread_id = 0;
499 { 516 {
500 AutoLock lock(lock_); 517 AutoLock lock(lock_);
501 if (shutdown_called_) 518 if (shutdown_called_)
502 return false; 519 return false;
503 520
521 // The trace_id is used for identifying the task in about:tracing.
522 sequenced.trace_id = trace_id_++;
523
524 TRACE_EVENT_FLOW_BEGIN0("task", "SequencedWorkerPool::PostTask",
525 TRACE_ID_MANGLE(GetTaskTraceID(sequenced, static_cast<void*>(this))));
526
504 // Now that we have the lock, apply the named token rules. 527 // Now that we have the lock, apply the named token rules.
505 if (optional_token_name) 528 if (optional_token_name)
506 sequenced.sequence_token_id = LockedGetNamedTokenID(*optional_token_name); 529 sequenced.sequence_token_id = LockedGetNamedTokenID(*optional_token_name);
507 530
508 pending_tasks_.push_back(sequenced); 531 pending_tasks_.push_back(sequenced);
509 pending_task_count_++; 532 pending_task_count_++;
510 if (shutdown_behavior == BLOCK_SHUTDOWN) 533 if (shutdown_behavior == BLOCK_SHUTDOWN)
511 blocking_shutdown_pending_task_count_++; 534 blocking_shutdown_pending_task_count_++;
512 535
513 create_thread_id = PrepareToStartAdditionalThreadIfHelpful(); 536 create_thread_id = PrepareToStartAdditionalThreadIfHelpful();
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 621
599 while (true) { 622 while (true) {
600 #if defined(OS_MACOSX) 623 #if defined(OS_MACOSX)
601 base::mac::ScopedNSAutoreleasePool autorelease_pool; 624 base::mac::ScopedNSAutoreleasePool autorelease_pool;
602 #endif 625 #endif
603 626
604 // See GetWork for what delete_these_outside_lock is doing. 627 // See GetWork for what delete_these_outside_lock is doing.
605 SequencedTask task; 628 SequencedTask task;
606 std::vector<Closure> delete_these_outside_lock; 629 std::vector<Closure> delete_these_outside_lock;
607 if (GetWork(&task, &delete_these_outside_lock)) { 630 if (GetWork(&task, &delete_these_outside_lock)) {
631 TRACE_EVENT_FLOW_END0("task", "SequencedWorkerPool::PostTask",
632 TRACE_ID_MANGLE(GetTaskTraceID(task, static_cast<void*>(this))));
633 TRACE_EVENT2("task", "SequencedWorkerPool::ThreadLoop",
634 "src_file", task.posted_from.file_name(),
635 "src_func", task.posted_from.function_name());
608 int new_thread_id = WillRunWorkerTask(task); 636 int new_thread_id = WillRunWorkerTask(task);
609 { 637 {
610 AutoUnlock unlock(lock_); 638 AutoUnlock unlock(lock_);
611 // There may be more work available, so wake up another 639 // There may be more work available, so wake up another
612 // worker thread. (Technically not required, since we 640 // worker thread. (Technically not required, since we
613 // already get a signal for each new task, but it doesn't 641 // already get a signal for each new task, but it doesn't
614 // hurt.) 642 // hurt.)
615 SignalHasWork(); 643 SignalHasWork();
616 delete_these_outside_lock.clear(); 644 delete_these_outside_lock.clear();
617 645
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 void SequencedWorkerPool::SignalHasWorkForTesting() { 1043 void SequencedWorkerPool::SignalHasWorkForTesting() {
1016 inner_->SignalHasWorkForTesting(); 1044 inner_->SignalHasWorkForTesting();
1017 } 1045 }
1018 1046
1019 void SequencedWorkerPool::Shutdown() { 1047 void SequencedWorkerPool::Shutdown() {
1020 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); 1048 DCHECK(constructor_message_loop_->BelongsToCurrentThread());
1021 inner_->Shutdown(); 1049 inner_->Shutdown();
1022 } 1050 }
1023 1051
1024 } // namespace base 1052 } // namespace base
OLDNEW
« base/message_loop.h ('K') | « base/message_loop.cc ('k') | ipc/ipc_channel_nacl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698