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

Unified Diff: base/threading/sequenced_worker_pool.cc

Issue 2491613004: Make base::Timer sequence-friendly. (Closed)
Patch Set: rebase Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/timer/timer.h » ('j') | base/timer/timer.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/threading/sequenced_worker_pool.cc
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 61cef6adf6b01c360299b2940f7c473ef3684ac8..e72b533acb22569715cddedd5e4e64ab71880f96 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -381,6 +381,13 @@ class SequencedWorkerPool::Inner {
CLEANUP_DONE,
};
+ // Clears ScheduledTasks in |delete_these_outside_lock| while ensuring that
+ // |this_worker| has the desired task info context for ~ScheduledTask() to
+ // allow RunsTasksOnCurrentThread() like checks.
+ void DeleteTheseOutsideLockHelper(
vmpstr 2016/12/03 01:14:04 WDYT about just "DeleteWithoutLock" with "tasks_to
gab 2016/12/23 20:22:10 Done on https://codereview.chromium.org/2581213002
+ std::vector<SequencedTask>* delete_these_outside_lock,
+ Worker* this_worker);
+
// Helper used by PostTask() to complete the work when redirection is on.
// Returns true if the task may run at some point in the future and false if
// it will definitely not run.
@@ -418,7 +425,7 @@ class SequencedWorkerPool::Inner {
// See the implementation for a more detailed description.
GetWorkStatus GetWork(SequencedTask* task,
TimeDelta* wait_time,
- std::vector<Closure>* delete_these_outside_lock);
+ std::vector<SequencedTask>* delete_these_outside_lock);
void HandleCleanup();
@@ -977,7 +984,7 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
// See GetWork for what delete_these_outside_lock is doing.
SequencedTask task;
TimeDelta wait_time;
- std::vector<Closure> delete_these_outside_lock;
+ std::vector<SequencedTask> delete_these_outside_lock;
GetWorkStatus status =
GetWork(&task, &wait_time, &delete_these_outside_lock);
if (status == GET_WORK_FOUND) {
@@ -994,7 +1001,7 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
// already get a signal for each new task, but it doesn't
// hurt.)
SignalHasWork();
- delete_these_outside_lock.clear();
+ DeleteTheseOutsideLockHelper(&delete_these_outside_lock, this_worker);
// Complete thread creation outside the lock if necessary.
if (new_thread_id)
@@ -1025,7 +1032,8 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
switch (status) {
case GET_WORK_WAIT: {
AutoUnlock unlock(lock_);
- delete_these_outside_lock.clear();
+ DeleteTheseOutsideLockHelper(&delete_these_outside_lock,
+ this_worker);
}
break;
case GET_WORK_NOT_FOUND:
@@ -1047,7 +1055,7 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
// help this case.
if (shutdown_called_ && blocking_shutdown_pending_task_count_ == 0) {
AutoUnlock unlock(lock_);
- delete_these_outside_lock.clear();
+ DeleteTheseOutsideLockHelper(&delete_these_outside_lock, this_worker);
break;
}
@@ -1055,7 +1063,7 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
// deletion must happen outside of the lock.
if (delete_these_outside_lock.size()) {
AutoUnlock unlock(lock_);
- delete_these_outside_lock.clear();
+ DeleteTheseOutsideLockHelper(&delete_these_outside_lock, this_worker);
// Since the lock has been released, |status| may no longer be
// accurate. It might read GET_WORK_WAIT even if there are tasks
@@ -1078,6 +1086,9 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
}
waiting_thread_count_--;
}
+ // |delete_these_outside_lock| should have been cleared via
+ // DeleteTheseOutsideLockHelper() above already.
+ DCHECK(delete_these_outside_lock.empty());
}
} // Release lock_.
@@ -1089,6 +1100,19 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
can_shutdown_cv_.Signal();
}
+void SequencedWorkerPool::Inner::DeleteTheseOutsideLockHelper(
+ std::vector<SequencedTask>* delete_these_outside_lock,
+ Worker* this_worker) {
+ while (!delete_these_outside_lock->empty()) {
+ const SequencedTask& deleted_task = delete_these_outside_lock->back();
+ this_worker->set_running_task_info(
+ SequenceToken(deleted_task.sequence_token_id),
+ deleted_task.shutdown_behavior);
+ delete_these_outside_lock->pop_back();
+ this_worker->reset_running_task_info();
vmpstr 2016/12/03 01:14:04 Does this need to happen after every iteration, or
gab 2016/12/23 20:22:10 Done on https://codereview.chromium.org/2581213002
+ }
+}
+
void SequencedWorkerPool::Inner::HandleCleanup() {
DCHECK_EQ(AllPoolsState::USE_WORKER_POOL, g_all_pools_state);
@@ -1156,7 +1180,7 @@ int64_t SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() {
SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
SequencedTask* task,
TimeDelta* wait_time,
- std::vector<Closure>* delete_these_outside_lock) {
+ std::vector<SequencedTask>* delete_these_outside_lock) {
DCHECK_EQ(AllPoolsState::USE_WORKER_POOL, g_all_pools_state);
lock_.AssertAcquired();
@@ -1202,18 +1226,17 @@ SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
// shutdown. Delete it and get more work.
//
// Note that we do not want to delete unrunnable tasks. Deleting a task
- // can have side effects (like freeing some objects) and deleting a
- // task that's supposed to run after one that's currently running could
- // cause an obscure crash.
+ // can have side effects (like freeing some objects) and deleting a task
+ // that's supposed to run after one that's currently running could cause
+ // an obscure crash.
//
// We really want to delete these tasks outside the lock in case the
- // closures are holding refs to objects that want to post work from
- // their destructorss (which would deadlock). The closures are
- // internally refcounted, so we just need to keep a copy of them alive
- // until the lock is exited. The calling code can just clear() the
- // vector they passed to us once the lock is exited to make this
- // happen.
- delete_these_outside_lock->push_back(i->task);
+ // closures are holding refs to objects that want to post work from their
+ // destructors (which would deadlock). The closures are internally
+ // refcounted, so we just need to keep a copy of them alive until the lock
+ // is exited. The calling code can just clear() the vector they passed to
+ // us once the lock is exited to make this happen.
+ delete_these_outside_lock->push_back(*i);
pending_tasks_.erase(i++);
continue;
}
@@ -1224,7 +1247,7 @@ SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
status = GET_WORK_WAIT;
if (cleanup_state_ == CLEANUP_RUNNING) {
// Deferred tasks are deleted when cleaning up, see Inner::ThreadLoop.
- delete_these_outside_lock->push_back(i->task);
+ delete_these_outside_lock->push_back(*i);
pending_tasks_.erase(i);
}
break;
« no previous file with comments | « no previous file | base/timer/timer.h » ('j') | base/timer/timer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698