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 |