| 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 "base/threading/sequenced_worker_pool.h" | 5 #include "base/threading/sequenced_worker_pool.h" |
| 6 | 6 |
| 7 #include <stdint.h> |
| 8 |
| 7 #include <list> | 9 #include <list> |
| 8 #include <map> | 10 #include <map> |
| 9 #include <set> | 11 #include <set> |
| 10 #include <utility> | 12 #include <utility> |
| 11 #include <vector> | 13 #include <vector> |
| 12 | 14 |
| 13 #include "base/atomic_sequence_num.h" | 15 #include "base/atomic_sequence_num.h" |
| 14 #include "base/callback.h" | 16 #include "base/callback.h" |
| 15 #include "base/compiler_specific.h" | 17 #include "base/compiler_specific.h" |
| 16 #include "base/critical_closure.h" | 18 #include "base/critical_closure.h" |
| 17 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 18 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/macros.h" |
| 19 #include "base/memory/linked_ptr.h" | 22 #include "base/memory/linked_ptr.h" |
| 20 #include "base/stl_util.h" | 23 #include "base/stl_util.h" |
| 21 #include "base/strings/stringprintf.h" | 24 #include "base/strings/stringprintf.h" |
| 22 #include "base/synchronization/condition_variable.h" | 25 #include "base/synchronization/condition_variable.h" |
| 23 #include "base/synchronization/lock.h" | 26 #include "base/synchronization/lock.h" |
| 24 #include "base/thread_task_runner_handle.h" | 27 #include "base/thread_task_runner_handle.h" |
| 25 #include "base/threading/platform_thread.h" | 28 #include "base/threading/platform_thread.h" |
| 26 #include "base/threading/simple_thread.h" | 29 #include "base/threading/simple_thread.h" |
| 27 #include "base/threading/thread_local.h" | 30 #include "base/threading/thread_local.h" |
| 28 #include "base/threading/thread_restrictions.h" | 31 #include "base/threading/thread_restrictions.h" |
| 29 #include "base/time/time.h" | 32 #include "base/time/time.h" |
| 30 #include "base/trace_event/trace_event.h" | 33 #include "base/trace_event/trace_event.h" |
| 31 #include "base/tracked_objects.h" | 34 #include "base/tracked_objects.h" |
| 35 #include "build/build_config.h" |
| 32 | 36 |
| 33 #if defined(OS_MACOSX) | 37 #if defined(OS_MACOSX) |
| 34 #include "base/mac/scoped_nsautorelease_pool.h" | 38 #include "base/mac/scoped_nsautorelease_pool.h" |
| 35 #elif defined(OS_WIN) | 39 #elif defined(OS_WIN) |
| 36 #include "base/win/scoped_com_initializer.h" | 40 #include "base/win/scoped_com_initializer.h" |
| 37 #endif | 41 #endif |
| 38 | 42 |
| 39 #if !defined(OS_NACL) | 43 #if !defined(OS_NACL) |
| 40 #include "base/metrics/histogram.h" | 44 #include "base/metrics/histogram.h" |
| 41 #endif | 45 #endif |
| (...skipping 13 matching lines...) Expand all Loading... |
| 55 : base::TrackingInfo(from_here, TimeTicks()), | 59 : base::TrackingInfo(from_here, TimeTicks()), |
| 56 sequence_token_id(0), | 60 sequence_token_id(0), |
| 57 trace_id(0), | 61 trace_id(0), |
| 58 sequence_task_number(0), | 62 sequence_task_number(0), |
| 59 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} | 63 shutdown_behavior(SequencedWorkerPool::BLOCK_SHUTDOWN) {} |
| 60 | 64 |
| 61 ~SequencedTask() {} | 65 ~SequencedTask() {} |
| 62 | 66 |
| 63 int sequence_token_id; | 67 int sequence_token_id; |
| 64 int trace_id; | 68 int trace_id; |
| 65 int64 sequence_task_number; | 69 int64_t sequence_task_number; |
| 66 SequencedWorkerPool::WorkerShutdown shutdown_behavior; | 70 SequencedWorkerPool::WorkerShutdown shutdown_behavior; |
| 67 tracked_objects::Location posted_from; | 71 tracked_objects::Location posted_from; |
| 68 Closure task; | 72 Closure task; |
| 69 | 73 |
| 70 // Non-delayed tasks and delayed tasks are managed together by time-to-run | 74 // Non-delayed tasks and delayed tasks are managed together by time-to-run |
| 71 // order. We calculate the time by adding the posted time and the given delay. | 75 // order. We calculate the time by adding the posted time and the given delay. |
| 72 TimeTicks time_to_run; | 76 TimeTicks time_to_run; |
| 73 }; | 77 }; |
| 74 | 78 |
| 75 struct SequencedTaskLessThan { | 79 struct SequencedTaskLessThan { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 const Closure& task, | 210 const Closure& task, |
| 207 TimeDelta delay) { | 211 TimeDelta delay) { |
| 208 // There's no way to run nested tasks, so simply forward to | 212 // There's no way to run nested tasks, so simply forward to |
| 209 // PostDelayedTask. | 213 // PostDelayedTask. |
| 210 return PostDelayedTask(from_here, task, delay); | 214 return PostDelayedTask(from_here, task, delay); |
| 211 } | 215 } |
| 212 | 216 |
| 213 // Create a process-wide unique ID to represent this task in trace events. This | 217 // Create a process-wide unique ID to represent this task in trace events. This |
| 214 // will be mangled with a Process ID hash to reduce the likelyhood of colliding | 218 // will be mangled with a Process ID hash to reduce the likelyhood of colliding |
| 215 // with MessageLoop pointers on other processes. | 219 // with MessageLoop pointers on other processes. |
| 216 uint64 GetTaskTraceID(const SequencedTask& task, | 220 uint64_t GetTaskTraceID(const SequencedTask& task, void* pool) { |
| 217 void* pool) { | 221 return (static_cast<uint64_t>(task.trace_id) << 32) | |
| 218 return (static_cast<uint64>(task.trace_id) << 32) | | 222 static_cast<uint64_t>(reinterpret_cast<intptr_t>(pool)); |
| 219 static_cast<uint64>(reinterpret_cast<intptr_t>(pool)); | |
| 220 } | 223 } |
| 221 | 224 |
| 222 } // namespace | 225 } // namespace |
| 223 | 226 |
| 224 // Worker --------------------------------------------------------------------- | 227 // Worker --------------------------------------------------------------------- |
| 225 | 228 |
| 226 class SequencedWorkerPool::Worker : public SimpleThread { | 229 class SequencedWorkerPool::Worker : public SimpleThread { |
| 227 public: | 230 public: |
| 228 // Hold a (cyclic) ref to |worker_pool|, since we want to keep it | 231 // Hold a (cyclic) ref to |worker_pool|, since we want to keep it |
| 229 // around as long as we are running. | 232 // around as long as we are running. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 CLEANUP_RUNNING, | 343 CLEANUP_RUNNING, |
| 341 CLEANUP_FINISHING, | 344 CLEANUP_FINISHING, |
| 342 CLEANUP_DONE, | 345 CLEANUP_DONE, |
| 343 }; | 346 }; |
| 344 | 347 |
| 345 // Called from within the lock, this converts the given token name into a | 348 // Called from within the lock, this converts the given token name into a |
| 346 // token ID, creating a new one if necessary. | 349 // token ID, creating a new one if necessary. |
| 347 int LockedGetNamedTokenID(const std::string& name); | 350 int LockedGetNamedTokenID(const std::string& name); |
| 348 | 351 |
| 349 // Called from within the lock, this returns the next sequence task number. | 352 // Called from within the lock, this returns the next sequence task number. |
| 350 int64 LockedGetNextSequenceTaskNumber(); | 353 int64_t LockedGetNextSequenceTaskNumber(); |
| 351 | 354 |
| 352 // Gets new task. There are 3 cases depending on the return value: | 355 // Gets new task. There are 3 cases depending on the return value: |
| 353 // | 356 // |
| 354 // 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should | 357 // 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should |
| 355 // be run immediately. | 358 // be run immediately. |
| 356 // 2) If the return value is |GET_WORK_NOT_FOUND|, there are no tasks to run, | 359 // 2) If the return value is |GET_WORK_NOT_FOUND|, there are no tasks to run, |
| 357 // and |task| is not filled in. In this case, the caller should wait until | 360 // and |task| is not filled in. In this case, the caller should wait until |
| 358 // a task is posted. | 361 // a task is posted. |
| 359 // 3) If the return value is |GET_WORK_WAIT|, there are no tasks to run | 362 // 3) If the return value is |GET_WORK_WAIT|, there are no tasks to run |
| 360 // immediately, and |task| is not filled in. Likewise, |wait_time| is | 363 // immediately, and |task| is not filled in. Likewise, |wait_time| is |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 | 459 |
| 457 // A set of all pending tasks in time-to-run order. These are tasks that are | 460 // A set of all pending tasks in time-to-run order. These are tasks that are |
| 458 // either waiting for a thread to run on, waiting for their time to run, | 461 // either waiting for a thread to run on, waiting for their time to run, |
| 459 // or blocked on a previous task in their sequence. We have to iterate over | 462 // or blocked on a previous task in their sequence. We have to iterate over |
| 460 // the tasks by time-to-run order, so we use the set instead of the | 463 // the tasks by time-to-run order, so we use the set instead of the |
| 461 // traditional priority_queue. | 464 // traditional priority_queue. |
| 462 typedef std::set<SequencedTask, SequencedTaskLessThan> PendingTaskSet; | 465 typedef std::set<SequencedTask, SequencedTaskLessThan> PendingTaskSet; |
| 463 PendingTaskSet pending_tasks_; | 466 PendingTaskSet pending_tasks_; |
| 464 | 467 |
| 465 // The next sequence number for a new sequenced task. | 468 // The next sequence number for a new sequenced task. |
| 466 int64 next_sequence_task_number_; | 469 int64_t next_sequence_task_number_; |
| 467 | 470 |
| 468 // Number of tasks in the pending_tasks_ list that are marked as blocking | 471 // Number of tasks in the pending_tasks_ list that are marked as blocking |
| 469 // shutdown. | 472 // shutdown. |
| 470 size_t blocking_shutdown_pending_task_count_; | 473 size_t blocking_shutdown_pending_task_count_; |
| 471 | 474 |
| 472 // Lists all sequence tokens currently executing. | 475 // Lists all sequence tokens currently executing. |
| 473 std::set<int> current_sequences_; | 476 std::set<int> current_sequences_; |
| 474 | 477 |
| 475 // An ID for each posted task to distinguish the task from others in traces. | 478 // An ID for each posted task to distinguish the task from others in traces. |
| 476 int trace_id_; | 479 int trace_id_; |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 named_sequence_tokens_.find(name); | 937 named_sequence_tokens_.find(name); |
| 935 if (found != named_sequence_tokens_.end()) | 938 if (found != named_sequence_tokens_.end()) |
| 936 return found->second; // Got an existing one. | 939 return found->second; // Got an existing one. |
| 937 | 940 |
| 938 // Create a new one for this name. | 941 // Create a new one for this name. |
| 939 SequenceToken result = GetSequenceToken(); | 942 SequenceToken result = GetSequenceToken(); |
| 940 named_sequence_tokens_.insert(std::make_pair(name, result.id_)); | 943 named_sequence_tokens_.insert(std::make_pair(name, result.id_)); |
| 941 return result.id_; | 944 return result.id_; |
| 942 } | 945 } |
| 943 | 946 |
| 944 int64 SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() { | 947 int64_t SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() { |
| 945 lock_.AssertAcquired(); | 948 lock_.AssertAcquired(); |
| 946 // We assume that we never create enough tasks to wrap around. | 949 // We assume that we never create enough tasks to wrap around. |
| 947 return next_sequence_task_number_++; | 950 return next_sequence_task_number_++; |
| 948 } | 951 } |
| 949 | 952 |
| 950 SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork( | 953 SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork( |
| 951 SequencedTask* task, | 954 SequencedTask* task, |
| 952 TimeDelta* wait_time, | 955 TimeDelta* wait_time, |
| 953 std::vector<Closure>* delete_these_outside_lock) { | 956 std::vector<Closure>* delete_these_outside_lock) { |
| 954 lock_.AssertAcquired(); | 957 lock_.AssertAcquired(); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { | 1334 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { |
| 1332 DCHECK(constructor_task_runner_->BelongsToCurrentThread()); | 1335 DCHECK(constructor_task_runner_->BelongsToCurrentThread()); |
| 1333 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); | 1336 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); |
| 1334 } | 1337 } |
| 1335 | 1338 |
| 1336 bool SequencedWorkerPool::IsShutdownInProgress() { | 1339 bool SequencedWorkerPool::IsShutdownInProgress() { |
| 1337 return inner_->IsShutdownInProgress(); | 1340 return inner_->IsShutdownInProgress(); |
| 1338 } | 1341 } |
| 1339 | 1342 |
| 1340 } // namespace base | 1343 } // namespace base |
| OLD | NEW |