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

Side by Side Diff: base/task_scheduler/task_tracker.cc

Issue 1705943002: TaskScheduler [5/9] Task Tracker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s_3_pq
Patch Set: CR gab #41 (fix a comment) Created 4 years, 9 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
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/task_scheduler/task_tracker.h"
6
7 #include "base/callback.h"
8 #include "base/debug/task_annotator.h"
9 #include "base/metrics/histogram_macros.h"
10
11 namespace base {
12 namespace internal {
13
14 namespace {
15
16 const char kQueueFunctionName[] = "base::PostTask";
17
18 // Upper bound for the
19 // TaskScheduler.BlockShutdownTasksPostedDuringShutdown histogram.
20 const size_t kMaxBlockShutdownTasksPostedDuringShutdown = 1000;
21
22 void RecordNumBlockShutdownTasksPostedDuringShutdown(size_t value) {
23 UMA_HISTOGRAM_CUSTOM_COUNTS(
24 "TaskScheduler.BlockShutdownTasksPostedDuringShutdown", value, 1,
25 kMaxBlockShutdownTasksPostedDuringShutdown, 50);
26 }
27
28 } // namespace
29
30 TaskTracker::TaskTracker() = default;
31 TaskTracker::~TaskTracker() = default;
32
33 void TaskTracker::Shutdown() {
34 AutoSchedulerLock auto_lock(lock_);
35
36 // This method should only be called once.
37 DCHECK(!shutdown_completed_);
38 DCHECK(!shutdown_cv_);
39
40 shutdown_cv_ = lock_.CreateConditionVariable();
41
42 // Wait until the number of tasks blocking shutdown is zero.
43 while (num_tasks_blocking_shutdown_ != 0)
44 shutdown_cv_->Wait();
45
46 shutdown_cv_.reset();
47 shutdown_completed_ = true;
48
49 // Record the TaskScheduler.BlockShutdownTasksPostedDuringShutdown if less
50 // than |kMaxBlockShutdownTasksPostedDuringShutdown| BLOCK_SHUTDOWN tasks were
51 // posted during shutdown. Otherwise, the histogram has already been recorded
52 // in BeforePostTask().
53 if (num_block_shutdown_tasks_posted_during_shutdown_ <
54 kMaxBlockShutdownTasksPostedDuringShutdown) {
55 RecordNumBlockShutdownTasksPostedDuringShutdown(
56 num_block_shutdown_tasks_posted_during_shutdown_);
57 }
58 }
59
60 void TaskTracker::PostTask(
61 const Callback<void(scoped_ptr<Task>)>& post_task_callback,
62 scoped_ptr<Task> task) {
63 DCHECK(!post_task_callback.is_null());
64 DCHECK(task);
65
66 if (!BeforePostTask(task->traits.shutdown_behavior()))
67 return;
68
69 debug::TaskAnnotator task_annotator;
70 task_annotator.DidQueueTask(kQueueFunctionName, *task);
71
72 post_task_callback.Run(std::move(task));
73 }
74
75 void TaskTracker::RunTask(const Task* task) {
76 DCHECK(task);
77
78 const TaskShutdownBehavior shutdown_behavior =
79 task->traits.shutdown_behavior();
80 if (!BeforeRunTask(shutdown_behavior))
81 return;
82
83 debug::TaskAnnotator task_annotator;
84 task_annotator.RunTask(kQueueFunctionName, *task);
85
86 AfterRunTask(shutdown_behavior);
87 }
88
89 bool TaskTracker::IsShuttingDownForTesting() const {
90 AutoSchedulerLock auto_lock(lock_);
91 return !!shutdown_cv_;
92 }
93
94 bool TaskTracker::BeforePostTask(TaskShutdownBehavior shutdown_behavior) {
95 AutoSchedulerLock auto_lock(lock_);
96
97 if (shutdown_completed_) {
98 // A BLOCK_SHUTDOWN task posted after shutdown has completed is an ordering
99 // bug. This DCHECK aims to catch those early.
100 DCHECK_NE(shutdown_behavior, TaskShutdownBehavior::BLOCK_SHUTDOWN);
101
102 // No task is allowed to be posted after shutdown.
103 return false;
104 }
105
106 if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
107 // BLOCK_SHUTDOWN tasks block shutdown between the moment they are posted
108 // and the moment they complete their execution.
109 ++num_tasks_blocking_shutdown_;
110
111 if (shutdown_cv_) {
112 ++num_block_shutdown_tasks_posted_during_shutdown_;
113
114 if (num_block_shutdown_tasks_posted_during_shutdown_ ==
115 kMaxBlockShutdownTasksPostedDuringShutdown) {
116 // Record the TaskScheduler.BlockShutdownTasksPostedDuringShutdown
117 // histogram as soon as its upper bound is hit. That way, a value will
118 // be recorded even if an infinite number of BLOCK_SHUTDOWN tasks are
119 // posted, preventing shutdown to complete.
120 RecordNumBlockShutdownTasksPostedDuringShutdown(
121 num_block_shutdown_tasks_posted_during_shutdown_);
122 }
123 }
124
125 // A BLOCK_SHUTDOWN task is allowed to be posted iff shutdown hasn't
126 // completed.
127 return true;
128 }
129
130 // A non BLOCK_SHUTDOWN task is allowed to be posted iff shutdown hasn't
131 // started.
132 return !shutdown_cv_;
133 }
134
135 bool TaskTracker::BeforeRunTask(TaskShutdownBehavior shutdown_behavior) {
136 AutoSchedulerLock auto_lock(lock_);
137
138 if (shutdown_completed_) {
139 // Trying to run a BLOCK_SHUTDOWN task after shutdown has completed is
140 // unexpected as it either shouldn't have been posted if shutdown completed
141 // or should be blocking shutdown if it was posted before it did.
142 DCHECK_NE(shutdown_behavior, TaskShutdownBehavior::BLOCK_SHUTDOWN);
143
144 // A WorkerThread might extract a non BLOCK_SHUTDOWN task from a
145 // PriorityQueue after shutdown. It shouldn't be allowed to run it.
146 return false;
147 }
148
149 switch (shutdown_behavior) {
150 case TaskShutdownBehavior::BLOCK_SHUTDOWN:
151 DCHECK_GT(num_tasks_blocking_shutdown_, 0U);
152 return true;
153
154 case TaskShutdownBehavior::SKIP_ON_SHUTDOWN:
155 if (shutdown_cv_)
156 return false;
157
158 // SKIP_ON_SHUTDOWN tasks block shutdown while they are running.
159 ++num_tasks_blocking_shutdown_;
160 return true;
161
162 case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN:
163 return !shutdown_cv_;
164 }
165
166 NOTREACHED();
167 return false;
168 }
169
170 void TaskTracker::AfterRunTask(TaskShutdownBehavior shutdown_behavior) {
171 if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN ||
172 shutdown_behavior == TaskShutdownBehavior::SKIP_ON_SHUTDOWN) {
173 AutoSchedulerLock auto_lock(lock_);
174 DCHECK_GT(num_tasks_blocking_shutdown_, 0U);
175 --num_tasks_blocking_shutdown_;
176 if (num_tasks_blocking_shutdown_ == 0 && shutdown_cv_)
177 shutdown_cv_->Signal();
178 }
179 }
180
181 } // namespace internal
182 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698