summaryrefslogtreecommitdiff
path: root/base/task_scheduler
diff options
context:
space:
mode:
Diffstat (limited to 'base/task_scheduler')
-rw-r--r--base/task_scheduler/scheduler_lock_impl.cc23
-rw-r--r--base/task_scheduler/scheduler_lock_unittest.cc14
-rw-r--r--base/task_scheduler/scoped_set_task_priority_for_current_thread.cc41
-rw-r--r--base/task_scheduler/scoped_set_task_priority_for_current_thread.h36
-rw-r--r--base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc26
-rw-r--r--base/task_scheduler/sequence.cc26
-rw-r--r--base/task_scheduler/sequence.h38
-rw-r--r--base/task_scheduler/sequence_unittest.cc93
-rw-r--r--base/task_scheduler/task.cc12
-rw-r--r--base/task_scheduler/task.h11
-rw-r--r--base/task_scheduler/task_traits.cc56
-rw-r--r--base/task_scheduler/task_traits.h84
-rw-r--r--base/task_scheduler/test_utils.h19
13 files changed, 121 insertions, 358 deletions
diff --git a/base/task_scheduler/scheduler_lock_impl.cc b/base/task_scheduler/scheduler_lock_impl.cc
index d60f25939b..7480e18da1 100644
--- a/base/task_scheduler/scheduler_lock_impl.cc
+++ b/base/task_scheduler/scheduler_lock_impl.cc
@@ -67,30 +67,19 @@ class SafeAcquisitionTracker {
// Otherwise, make sure that the previous lock acquired is an allowed
// predecessor.
AutoLock auto_lock(allowed_predecessor_map_lock_);
- // Using at() is exception-safe here as |lock| was registered already.
const SchedulerLockImpl* allowed_predecessor =
allowed_predecessor_map_.at(lock);
DCHECK_EQ(acquired_locks->back(), allowed_predecessor);
}
- // Asserts that |lock|'s registered predecessor is safe. Because
- // SchedulerLocks are registered at construction time and any predecessor
- // specified on a SchedulerLock must already exist, the first registered
- // SchedulerLock in a potential chain must have a null predecessor and is thus
- // cycle-free. Any subsequent SchedulerLock with a predecessor must come from
- // the set of registered SchedulerLocks. Since the registered SchedulerLocks
- // only contain cycle-free SchedulerLocks, this subsequent SchedulerLock is
- // itself cycle-free and may be safely added to the registered SchedulerLock
- // set.
void AssertSafePredecessor(const SchedulerLockImpl* lock) const {
allowed_predecessor_map_lock_.AssertAcquired();
- // Using at() is exception-safe here as |lock| was registered already.
- const SchedulerLockImpl* predecessor = allowed_predecessor_map_.at(lock);
- if (predecessor) {
- DCHECK(allowed_predecessor_map_.find(predecessor) !=
- allowed_predecessor_map_.end())
- << "SchedulerLock was registered before its predecessor. "
- << "Potential cycle detected";
+ for (const SchedulerLockImpl* predecessor =
+ allowed_predecessor_map_.at(lock);
+ predecessor != nullptr;
+ predecessor = allowed_predecessor_map_.at(predecessor)) {
+ DCHECK_NE(predecessor, lock) <<
+ "Scheduler lock predecessor cycle detected.";
}
}
diff --git a/base/task_scheduler/scheduler_lock_unittest.cc b/base/task_scheduler/scheduler_lock_unittest.cc
index 55182479aa..daa50257f1 100644
--- a/base/task_scheduler/scheduler_lock_unittest.cc
+++ b/base/task_scheduler/scheduler_lock_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/rand_util.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
+#include "base/task_scheduler/test_utils.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -131,7 +131,7 @@ TEST(TaskSchedulerLock, AcquirePredecessorWrongOrder) {
EXPECT_DCHECK_DEATH({
lock.Acquire();
predecessor.Acquire();
- });
+ }, "");
}
TEST(TaskSchedulerLock, AcquireNonPredecessor) {
@@ -140,7 +140,7 @@ TEST(TaskSchedulerLock, AcquireNonPredecessor) {
EXPECT_DCHECK_DEATH({
lock1.Acquire();
lock2.Acquire();
- });
+ }, "");
}
TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
@@ -172,7 +172,7 @@ TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
EXPECT_DCHECK_DEATH({
lock1.Acquire();
lock3.Acquire();
- });
+ }, "");
}
TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
@@ -258,7 +258,7 @@ TEST(TaskSchedulerLock, SelfReferentialLock) {
SchedulerLock lock;
};
- EXPECT_DCHECK_DEATH({ SelfReferentialLock lock; });
+ EXPECT_DCHECK_DEATH({ SelfReferentialLock lock; }, "");
}
TEST(TaskSchedulerLock, PredecessorCycle) {
@@ -269,7 +269,7 @@ TEST(TaskSchedulerLock, PredecessorCycle) {
SchedulerLock lock2;
};
- EXPECT_DCHECK_DEATH({ LockCycle cycle; });
+ EXPECT_DCHECK_DEATH({ LockCycle cycle; }, "");
}
TEST(TaskSchedulerLock, PredecessorLongerCycle) {
@@ -288,7 +288,7 @@ TEST(TaskSchedulerLock, PredecessorLongerCycle) {
SchedulerLock lock5;
};
- EXPECT_DCHECK_DEATH({ LockCycle cycle; });
+ EXPECT_DCHECK_DEATH({ LockCycle cycle; }, "");
}
} // namespace
diff --git a/base/task_scheduler/scoped_set_task_priority_for_current_thread.cc b/base/task_scheduler/scoped_set_task_priority_for_current_thread.cc
deleted file mode 100644
index a163863d0f..0000000000
--- a/base/task_scheduler/scoped_set_task_priority_for_current_thread.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
-
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/threading/thread_local.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-LazyInstance<ThreadLocalPointer<const TaskPriority>>::Leaky
- tls_task_priority_for_current_thread = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-ScopedSetTaskPriorityForCurrentThread::ScopedSetTaskPriorityForCurrentThread(
- TaskPriority priority)
- : priority_(priority) {
- DCHECK(!tls_task_priority_for_current_thread.Get().Get());
- tls_task_priority_for_current_thread.Get().Set(&priority_);
-}
-
-ScopedSetTaskPriorityForCurrentThread::
- ~ScopedSetTaskPriorityForCurrentThread() {
- DCHECK_EQ(&priority_, tls_task_priority_for_current_thread.Get().Get());
- tls_task_priority_for_current_thread.Get().Set(nullptr);
-}
-
-TaskPriority GetTaskPriorityForCurrentThread() {
- const TaskPriority* priority =
- tls_task_priority_for_current_thread.Get().Get();
- return priority ? *priority : TaskPriority::USER_VISIBLE;
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scoped_set_task_priority_for_current_thread.h b/base/task_scheduler/scoped_set_task_priority_for_current_thread.h
deleted file mode 100644
index 4508911d9c..0000000000
--- a/base/task_scheduler/scoped_set_task_priority_for_current_thread.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TASK_SCHEDULER_SCOPED_SET_TASK_PRIORITY_FOR_CURRENT_THREAD_H_
-#define BASE_TASK_SCHEDULER_SCOPED_SET_TASK_PRIORITY_FOR_CURRENT_THREAD_H_
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/task_scheduler/task_traits.h"
-
-namespace base {
-namespace internal {
-
-class BASE_EXPORT ScopedSetTaskPriorityForCurrentThread {
- public:
- // Within the scope of this object, GetTaskPriorityForCurrentThread() will
- // return |priority|.
- ScopedSetTaskPriorityForCurrentThread(TaskPriority priority);
- ~ScopedSetTaskPriorityForCurrentThread();
-
- private:
- const TaskPriority priority_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedSetTaskPriorityForCurrentThread);
-};
-
-// Returns the priority of the TaskScheduler task running on the current thread,
-// or TaskPriority::USER_VISIBLE if no TaskScheduler task is running on the
-// current thread.
-BASE_EXPORT TaskPriority GetTaskPriorityForCurrentThread();
-
-} // namespace internal
-} // namespace base
-
-#endif // BASE_TASK_SCHEDULER_SCOPED_SET_TASK_PRIORITY_FOR_CURRENT_THREAD_H_
diff --git a/base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc b/base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc
deleted file mode 100644
index c497af6770..0000000000
--- a/base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
-
-#include "base/task_scheduler/task_traits.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-TEST(TaskSchedulerScopedSetTaskPriorityForCurrentThreadTest,
- ScopedSetTaskPriorityForCurrentThread) {
- EXPECT_EQ(TaskPriority::USER_VISIBLE, GetTaskPriorityForCurrentThread());
- {
- ScopedSetTaskPriorityForCurrentThread
- scoped_set_task_priority_for_current_thread(
- TaskPriority::USER_BLOCKING);
- EXPECT_EQ(TaskPriority::USER_BLOCKING, GetTaskPriorityForCurrentThread());
- }
- EXPECT_EQ(TaskPriority::USER_VISIBLE, GetTaskPriorityForCurrentThread());
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/sequence.cc b/base/task_scheduler/sequence.cc
index 601b5402d0..4ecb60568c 100644
--- a/base/task_scheduler/sequence.cc
+++ b/base/task_scheduler/sequence.cc
@@ -26,30 +26,24 @@ bool Sequence::PushTask(std::unique_ptr<Task> task) {
return queue_.size() == 1;
}
-std::unique_ptr<Task> Sequence::TakeTask() {
+const Task* Sequence::PeekTask() const {
AutoSchedulerLock auto_lock(lock_);
- DCHECK(!queue_.empty());
- DCHECK(queue_.front());
- const int priority_index =
- static_cast<int>(queue_.front()->traits.priority());
- DCHECK_GT(num_tasks_per_priority_[priority_index], 0U);
- --num_tasks_per_priority_[priority_index];
+ if (queue_.empty())
+ return nullptr;
- return std::move(queue_.front());
+ return queue_.front().get();
}
-TaskTraits Sequence::PeekTaskTraits() const {
+bool Sequence::PopTask() {
AutoSchedulerLock auto_lock(lock_);
DCHECK(!queue_.empty());
- DCHECK(queue_.front());
- return queue_.front()->traits;
-}
-bool Sequence::Pop() {
- AutoSchedulerLock auto_lock(lock_);
- DCHECK(!queue_.empty());
- DCHECK(!queue_.front());
+ const int priority_index =
+ static_cast<int>(queue_.front()->traits.priority());
+ DCHECK_GT(num_tasks_per_priority_[priority_index], 0U);
+ --num_tasks_per_priority_[priority_index];
+
queue_.pop();
return queue_.empty();
}
diff --git a/base/task_scheduler/sequence.h b/base/task_scheduler/sequence.h
index ed1d0ac401..3fa037fa35 100644
--- a/base/task_scheduler/sequence.h
+++ b/base/task_scheduler/sequence.h
@@ -13,7 +13,6 @@
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/sequence_token.h"
#include "base/task_scheduler/scheduler_lock.h"
#include "base/task_scheduler/sequence_sort_key.h"
#include "base/task_scheduler/task.h"
@@ -22,10 +21,7 @@
namespace base {
namespace internal {
-// A Sequence holds slots each containing up to a single Task that must be
-// executed in posting order.
-//
-// In comments below, an "empty Sequence" is a Sequence with no slot.
+// A sequence holds tasks that must be executed in posting order.
//
// Note: there is a known refcounted-ownership cycle in the Scheduler
// architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
@@ -44,38 +40,26 @@ class BASE_EXPORT Sequence : public RefCountedThreadSafe<Sequence> {
public:
Sequence();
- // Adds |task| in a new slot at the end of the Sequence. Returns true if the
- // Sequence was empty before this operation.
+ // Adds |task| at the end of the sequence's queue. Returns true if the
+ // sequence was empty before this operation.
bool PushTask(std::unique_ptr<Task> task);
- // Transfers ownership of the Task in the front slot of the Sequence to the
- // caller. The front slot of the Sequence will be nullptr and remain until
- // Pop(). Cannot be called on an empty Sequence or a Sequence whose front slot
- // is already nullptr.
- std::unique_ptr<Task> TakeTask();
-
- // Returns the TaskTraits of the Task in front of the Sequence. Cannot be
- // called on an empty Sequence or on a Sequence whose front slot is empty.
- TaskTraits PeekTaskTraits() const;
+ // Returns the task in front of the sequence's queue, if any.
+ const Task* PeekTask() const;
- // Removes the front slot of the Sequence. The front slot must have been
- // emptied by TakeTask() before this is called. Cannot be called on an empty
- // Sequence. Returns true if the Sequence is empty after this operation.
- bool Pop();
+ // Removes the task in front of the sequence's queue. Returns true if the
+ // sequence is empty after this operation. Cannot be called on an empty
+ // sequence.
+ bool PopTask();
- // Returns a SequenceSortKey representing the priority of the Sequence. Cannot
- // be called on an empty Sequence.
+ // Returns a SequenceSortKey representing the priority of the sequence. Cannot
+ // be called on an empty sequence.
SequenceSortKey GetSortKey() const;
- // Returns a token that uniquely identifies this Sequence.
- const SequenceToken& token() const { return token_; }
-
private:
friend class RefCountedThreadSafe<Sequence>;
~Sequence();
- const SequenceToken token_ = SequenceToken::Create();
-
// Synchronizes access to all members.
mutable SchedulerLock lock_;
diff --git a/base/task_scheduler/sequence_unittest.cc b/base/task_scheduler/sequence_unittest.cc
index c45d8a87d0..6a15299e1e 100644
--- a/base/task_scheduler/sequence_unittest.cc
+++ b/base/task_scheduler/sequence_unittest.cc
@@ -4,12 +4,7 @@
#include "base/task_scheduler/sequence.h"
-#include <utility>
-
-#include "base/bind.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/gtest_util.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,7 +13,6 @@ namespace internal {
namespace {
-
class TaskSchedulerSequenceTest : public testing::Test {
public:
TaskSchedulerSequenceTest()
@@ -62,7 +56,7 @@ class TaskSchedulerSequenceTest : public testing::Test {
std::unique_ptr<Task> task_e_owned_;
// Raw pointers to those same tasks for verification. This is needed because
- // the unique_ptrs above no longer point to the tasks once they have been
+ // the scoped_ptrs above no longer point to the tasks once they have been
// moved into a Sequence.
const Task* task_a_;
const Task* task_b_;
@@ -76,54 +70,54 @@ class TaskSchedulerSequenceTest : public testing::Test {
} // namespace
-TEST_F(TaskSchedulerSequenceTest, PushTakeRemove) {
+TEST_F(TaskSchedulerSequenceTest, PushPopPeek) {
scoped_refptr<Sequence> sequence(new Sequence);
// Push task A in the sequence. Its sequenced time should be updated and it
// should be in front of the sequence.
EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_)));
EXPECT_FALSE(task_a_->sequenced_time.is_null());
- EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
+ EXPECT_EQ(task_a_, sequence->PeekTask());
// Push task B, C and D in the sequence. Their sequenced time should be
// updated and task A should always remain in front of the sequence.
EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_)));
EXPECT_FALSE(task_b_->sequenced_time.is_null());
- EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
+ EXPECT_EQ(task_a_, sequence->PeekTask());
EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_)));
EXPECT_FALSE(task_c_->sequenced_time.is_null());
- EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
+ EXPECT_EQ(task_a_, sequence->PeekTask());
EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_)));
EXPECT_FALSE(task_d_->sequenced_time.is_null());
- EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
+ EXPECT_EQ(task_a_, sequence->PeekTask());
- // Get the task in front of the sequence. It should be task A.
- EXPECT_EQ(task_a_, sequence->TakeTask().get());
+ // Pop task A. Task B should now be in front.
+ EXPECT_FALSE(sequence->PopTask());
+ EXPECT_EQ(task_b_, sequence->PeekTask());
- // Remove the empty slot. Task B should now be in front.
- EXPECT_FALSE(sequence->Pop());
- EXPECT_EQ(task_b_, sequence->TakeTask().get());
+ // Pop task B. Task C should now be in front.
+ EXPECT_FALSE(sequence->PopTask());
+ EXPECT_EQ(task_c_, sequence->PeekTask());
- // Remove the empty slot. Task C should now be in front.
- EXPECT_FALSE(sequence->Pop());
- EXPECT_EQ(task_c_, sequence->TakeTask().get());
+ // Pop task C. Task D should now be in front.
+ EXPECT_FALSE(sequence->PopTask());
+ EXPECT_EQ(task_d_, sequence->PeekTask());
- // Remove the empty slot. Task D should now be in front.
- EXPECT_FALSE(sequence->Pop());
- EXPECT_EQ(task_d_, sequence->TakeTask().get());
-
- // Push task E in the sequence. Its sequenced time should be updated.
+ // Push task E in the sequence. Its sequenced time should be updated and
+ // task D should remain in front.
EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_)));
EXPECT_FALSE(task_e_->sequenced_time.is_null());
+ EXPECT_EQ(task_d_, sequence->PeekTask());
- // Remove the empty slot. Task E should now be in front.
- EXPECT_FALSE(sequence->Pop());
- EXPECT_EQ(task_e_, sequence->TakeTask().get());
+ // Pop task D. Task E should now be in front.
+ EXPECT_FALSE(sequence->PopTask());
+ EXPECT_EQ(task_e_, sequence->PeekTask());
- // Remove the empty slot. The sequence should now be empty.
- EXPECT_TRUE(sequence->Pop());
+ // Pop task E. The sequence should now be empty.
+ EXPECT_TRUE(sequence->PopTask());
+ EXPECT_EQ(nullptr, sequence->PeekTask());
}
TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
@@ -158,24 +152,21 @@ TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
// Pop task A. The highest priority is still USER_BLOCKING. The task in front
// of the sequence is now task B.
- sequence->TakeTask();
- sequence->Pop();
+ sequence->PopTask();
EXPECT_EQ(
SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time),
sequence->GetSortKey());
// Pop task B. The highest priority is still USER_BLOCKING. The task in front
// of the sequence is now task C.
- sequence->TakeTask();
- sequence->Pop();
+ sequence->PopTask();
EXPECT_EQ(
SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time),
sequence->GetSortKey());
// Pop task C. The highest priority is still USER_BLOCKING. The task in front
// of the sequence is now task D.
- sequence->TakeTask();
- sequence->Pop();
+ sequence->PopTask();
EXPECT_EQ(
SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
sequence->GetSortKey());
@@ -189,38 +180,10 @@ TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
// Pop task D. The highest priority is now from task E (BACKGROUND). The
// task in front of the sequence is now task E.
- sequence->TakeTask();
- sequence->Pop();
+ sequence->PopTask();
EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time),
sequence->GetSortKey());
}
-// Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
-// isn't empty.
-TEST_F(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
- scoped_refptr<Sequence> sequence(new Sequence);
- sequence->PushTask(
- MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
-
- EXPECT_DCHECK_DEATH({ sequence->Pop(); });
-}
-
-// Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
-// slot is empty.
-TEST_F(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) {
- scoped_refptr<Sequence> sequence(new Sequence);
- sequence->PushTask(
- MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
-
- EXPECT_TRUE(sequence->TakeTask());
- EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
-}
-
-// Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
-TEST_F(TaskSchedulerSequenceTest, TakeEmptySequence) {
- scoped_refptr<Sequence> sequence(new Sequence);
- EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
-}
-
} // namespace internal
} // namespace base
diff --git a/base/task_scheduler/task.cc b/base/task_scheduler/task.cc
index 3780c16dcb..8a589a2021 100644
--- a/base/task_scheduler/task.cc
+++ b/base/task_scheduler/task.cc
@@ -10,20 +10,12 @@ namespace internal {
Task::Task(const tracked_objects::Location& posted_from,
const Closure& task,
const TaskTraits& traits,
- TimeDelta delay)
+ const TimeDelta& delay)
: PendingTask(posted_from,
task,
delay.is_zero() ? TimeTicks() : TimeTicks::Now() + delay,
false), // Not nestable.
- // Prevent a delayed BLOCK_SHUTDOWN task from blocking shutdown before
- // being scheduled by changing its shutdown behavior to SKIP_ON_SHUTDOWN.
- traits(!delay.is_zero() &&
- traits.shutdown_behavior() ==
- TaskShutdownBehavior::BLOCK_SHUTDOWN
- ? TaskTraits(traits).WithShutdownBehavior(
- TaskShutdownBehavior::SKIP_ON_SHUTDOWN)
- : traits),
- delay(delay) {}
+ traits(traits) {}
Task::~Task() = default;
diff --git a/base/task_scheduler/task.h b/base/task_scheduler/task.h
index c5b9bdb53b..2b53c690fd 100644
--- a/base/task_scheduler/task.h
+++ b/base/task_scheduler/task.h
@@ -23,22 +23,17 @@ namespace internal {
// profiling inherited from PendingTask.
struct BASE_EXPORT Task : public PendingTask {
// |posted_from| is the site the task was posted from. |task| is the closure
- // to run. |traits_in| is metadata about the task. |delay| is a delay that
- // must expire before the Task runs. If |delay| is non-zero and the shutdown
- // behavior in |traits| is BLOCK_SHUTDOWN, the shutdown behavior is
- // automatically adjusted to SKIP_ON_SHUTDOWN.
+ // to run. |traits| is metadata about the task. |delay| is a delay that must
+ // expire before the Task runs.
Task(const tracked_objects::Location& posted_from,
const Closure& task,
const TaskTraits& traits,
- TimeDelta delay);
+ const TimeDelta& delay);
~Task();
// The TaskTraits of this task.
const TaskTraits traits;
- // The delay that must expire before the task runs.
- const TimeDelta delay;
-
// The time at which the task was inserted in its sequence. For an undelayed
// task, this happens at post time. For a delayed task, this happens some
// time after the task's delay has expired. If the task hasn't been inserted
diff --git a/base/task_scheduler/task_traits.cc b/base/task_scheduler/task_traits.cc
index 6acf3244f5..dd55535852 100644
--- a/base/task_scheduler/task_traits.cc
+++ b/base/task_scheduler/task_traits.cc
@@ -8,29 +8,20 @@
#include <ostream>
-#include "base/logging.h"
-#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
-
namespace base {
// Do not rely on defaults hard-coded below beyond the guarantees described in
// the header; anything else is subject to change. Tasks should explicitly
// request defaults if the behavior is critical to the task.
TaskTraits::TaskTraits()
- : may_block_(false),
- with_base_sync_primitives_(false),
- priority_(internal::GetTaskPriorityForCurrentThread()),
+ : with_file_io_(false),
+ priority_(TaskPriority::BACKGROUND),
shutdown_behavior_(TaskShutdownBehavior::SKIP_ON_SHUTDOWN) {}
TaskTraits::~TaskTraits() = default;
-TaskTraits& TaskTraits::MayBlock() {
- may_block_ = true;
- return *this;
-}
-
-TaskTraits& TaskTraits::WithBaseSyncPrimitives() {
- with_base_sync_primitives_ = true;
+TaskTraits& TaskTraits::WithFileIO() {
+ with_file_io_ = true;
return *this;
}
@@ -45,41 +36,34 @@ TaskTraits& TaskTraits::WithShutdownBehavior(
return *this;
}
-const char* TaskPriorityToString(TaskPriority task_priority) {
+std::ostream& operator<<(std::ostream& os, const TaskPriority& task_priority) {
switch (task_priority) {
case TaskPriority::BACKGROUND:
- return "BACKGROUND";
+ os << "BACKGROUND";
+ break;
case TaskPriority::USER_VISIBLE:
- return "USER_VISIBLE";
+ os << "USER_VISIBLE";
+ break;
case TaskPriority::USER_BLOCKING:
- return "USER_BLOCKING";
+ os << "USER_BLOCKING";
+ break;
}
- NOTREACHED();
- return "";
+ return os;
}
-const char* TaskShutdownBehaviorToString(
- TaskShutdownBehavior shutdown_behavior) {
+std::ostream& operator<<(std::ostream& os,
+ const TaskShutdownBehavior& shutdown_behavior) {
switch (shutdown_behavior) {
case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN:
- return "CONTINUE_ON_SHUTDOWN";
+ os << "CONTINUE_ON_SHUTDOWN";
+ break;
case TaskShutdownBehavior::SKIP_ON_SHUTDOWN:
- return "SKIP_ON_SHUTDOWN";
+ os << "SKIP_ON_SHUTDOWN";
+ break;
case TaskShutdownBehavior::BLOCK_SHUTDOWN:
- return "BLOCK_SHUTDOWN";
+ os << "BLOCK_SHUTDOWN";
+ break;
}
- NOTREACHED();
- return "";
-}
-
-std::ostream& operator<<(std::ostream& os, const TaskPriority& task_priority) {
- os << TaskPriorityToString(task_priority);
- return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
- const TaskShutdownBehavior& shutdown_behavior) {
- os << TaskShutdownBehaviorToString(shutdown_behavior);
return os;
}
diff --git a/base/task_scheduler/task_traits.h b/base/task_scheduler/task_traits.h
index 435fdac9af..0c0d304dcf 100644
--- a/base/task_scheduler/task_traits.h
+++ b/base/task_scheduler/task_traits.h
@@ -78,57 +78,19 @@ enum class TaskShutdownBehavior {
// Describes metadata for a single task or a group of tasks.
class BASE_EXPORT TaskTraits {
public:
- // Constructs a default TaskTraits for tasks that
- // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
- // (2) prefer inheriting the current priority to specifying their own, and
- // (3) can either block shutdown or be skipped on shutdown
- // (TaskScheduler implementation is free to choose a fitting default).
- // Tasks that require stricter guarantees and/or know the specific
- // TaskPriority appropriate for them should highlight those by requesting
+ // Constructs a default TaskTraits for tasks with
+ // (1) no I/O,
+ // (2) low priority, and
+ // (3) may block shutdown or be skipped on shutdown.
+ // Tasks that require stricter guarantees should highlight those by requesting
// explicit traits below.
TaskTraits();
TaskTraits(const TaskTraits& other) = default;
TaskTraits& operator=(const TaskTraits& other) = default;
~TaskTraits();
- // Tasks with this trait may block. This includes but is not limited to tasks
- // that wait on synchronous file I/O operations: read or write a file from
- // disk, interact with a pipe or a socket, rename or delete a file, enumerate
- // files in a directory, etc. This trait isn't required for the mere use of
- // locks. For tasks that block on base/ synchronization primitives, see
- // WithBaseSyncPrimitives().
- TaskTraits& MayBlock();
-
- // Tasks with this trait will pass base::AssertWaitAllowed(), i.e. will be
- // allowed on the following methods :
- // - base::WaitableEvent::Wait
- // - base::ConditionVariable::Wait
- // - base::PlatformThread::Join
- // - base::PlatformThread::Sleep
- // - base::Process::WaitForExit
- // - base::Process::WaitForExitWithTimeout
- //
- // Tasks should generally not use these methods.
- //
- // Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
- // that should happen after the wait in a callback and post that callback from
- // where the WaitableEvent or ConditionVariable would have been signaled. If
- // something needs to be scheduled after many tasks have executed, use
- // base::BarrierClosure.
- //
- // Avoid creating threads. Instead, use
- // base::Create(Sequenced|SingleTreaded)TaskRunnerWithTraits(). If a thread is
- // really needed, make it non-joinable and add cleanup work at the end of the
- // thread's main function (if using base::Thread, override Cleanup()).
- //
- // On Windows, join processes asynchronously using base::win::ObjectWatcher.
- //
- // MayBlock() must be specified in conjunction with this trait if and only if
- // removing usage of methods listed above in the labeled tasks would still
- // result in tasks that may block (per MayBlock()'s definition).
- //
- // In doubt, consult with //base/task_scheduler/OWNERS.
- TaskTraits& WithBaseSyncPrimitives();
+ // Allows tasks with these traits to do file I/O.
+ TaskTraits& WithFileIO();
// Applies |priority| to tasks with these traits.
TaskTraits& WithPriority(TaskPriority priority);
@@ -136,11 +98,8 @@ class BASE_EXPORT TaskTraits {
// Applies |shutdown_behavior| to tasks with these traits.
TaskTraits& WithShutdownBehavior(TaskShutdownBehavior shutdown_behavior);
- // Returns true if tasks with these traits may block.
- bool may_block() const { return may_block_; }
-
- // Returns true if tasks with these traits may use base/ sync primitives.
- bool with_base_sync_primitives() const { return with_base_sync_primitives_; }
+ // Returns true if file I/O is allowed by these traits.
+ bool with_file_io() const { return with_file_io_; }
// Returns the priority of tasks with these traits.
TaskPriority priority() const { return priority_; }
@@ -149,22 +108,29 @@ class BASE_EXPORT TaskTraits {
TaskShutdownBehavior shutdown_behavior() const { return shutdown_behavior_; }
private:
- bool may_block_;
- bool with_base_sync_primitives_;
+ bool with_file_io_;
TaskPriority priority_;
TaskShutdownBehavior shutdown_behavior_;
};
-// Returns string literals for the enums defined in this file. These methods
-// should only be used for tracing and debugging.
-BASE_EXPORT const char* TaskPriorityToString(TaskPriority task_priority);
-BASE_EXPORT const char* TaskShutdownBehaviorToString(
- TaskShutdownBehavior task_priority);
+// Describes how tasks are executed by a task runner.
+enum class ExecutionMode {
+ // Can execute multiple tasks at a time in any order.
+ PARALLEL,
+
+ // Executes one task at a time in posting order. The sequence’s priority is
+ // equivalent to the highest priority pending task in the sequence.
+ SEQUENCED,
-// Stream operators so that the enums defined in this file can be used in
-// DCHECK and EXPECT statements.
+ // Executes one task at a time on a single thread in posting order.
+ SINGLE_THREADED,
+};
+
+// Stream operators so TaskPriority and TaskShutdownBehavior can be used in
+// DCHECK statements.
BASE_EXPORT std::ostream& operator<<(std::ostream& os,
const TaskPriority& shutdown_behavior);
+
BASE_EXPORT std::ostream& operator<<(
std::ostream& os,
const TaskShutdownBehavior& shutdown_behavior);
diff --git a/base/task_scheduler/test_utils.h b/base/task_scheduler/test_utils.h
index dbd1227f52..bafd09aa2a 100644
--- a/base/task_scheduler/test_utils.h
+++ b/base/task_scheduler/test_utils.h
@@ -5,16 +5,15 @@
#ifndef BASE_TASK_SCHEDULER_TEST_UTILS_H_
#define BASE_TASK_SCHEDULER_TEST_UTILS_H_
-namespace base {
-namespace internal {
-namespace test {
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
-// An enumeration of possible task scheduler TaskRunner types. Used to
-// parametrize relevant task_scheduler tests.
-enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED };
-
-} // namespace test
-} // namespace internal
-} // namespace base
+// Death tests misbehave on Android.
+#if DCHECK_IS_ON() && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
+#define EXPECT_DCHECK_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
+#else
+#define EXPECT_DCHECK_DEATH(statement, regex)
+#endif
#endif // BASE_TASK_SCHEDULER_TEST_UTILS_H_