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

Unified Diff: base/test/scoped_task_scheduler.cc

Issue 2557083002: Run ScopedTaskScheduler tasks synchronously. (Closed)
Patch Set: git cl try Created 4 years 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
Index: base/test/scoped_task_scheduler.cc
diff --git a/base/test/scoped_task_scheduler.cc b/base/test/scoped_task_scheduler.cc
index 2cf5b33cf6422b494df754f0a375f9d8af4b82d0..d4b57674237615155081aaf04379df76e0c98960 100644
--- a/base/test/scoped_task_scheduler.cc
+++ b/base/test/scoped_task_scheduler.cc
@@ -4,37 +4,259 @@
#include "base/test/scoped_task_scheduler.h"
+#include <memory>
+#include <utility>
#include <vector>
#include "base/bind.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram_base.h"
+#include "base/run_loop.h"
+#include "base/sequence_token.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "base/task_scheduler/task.h"
#include "base/task_scheduler/task_scheduler.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
+#include "base/task_scheduler/task_tracker.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
+#include "base/files/file_descriptor_watcher_posix.h"
+#endif
namespace base {
namespace test {
-ScopedTaskScheduler::ScopedTaskScheduler() {
- DCHECK(!TaskScheduler::GetInstance());
+namespace {
+
+enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED };
+
+class TestTaskScheduler : public TaskScheduler {
+ public:
+ TestTaskScheduler(ScopedTaskScheduler::Options options);
+ ~TestTaskScheduler() override;
+
+ // TaskScheduler:
+ void PostTaskWithTraits(const tracked_objects::Location& from_here,
+ const TaskTraits& traits,
+ const Closure& task) override;
+ scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
+ const TaskTraits& traits) override;
+ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
+ const TaskTraits& traits) override;
+ scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits(
+ const TaskTraits& traits) override;
+ std::vector<const HistogramBase*> GetHistograms() const override;
+ void Shutdown() override;
+ void FlushForTesting() override;
+
+ // Posts |task| to this TaskScheduler with |sequence_token|.
robliao 2016/12/09 01:32:54 Nit: Add what the bool (return value) indicates.
fdoray 2016/12/09 16:26:41 Done.
+ bool PostTask(std::unique_ptr<internal::Task> task,
+ const SequenceToken& sequence_token);
+
+ // Runs |task| with |sequence_token| using this TaskScheduler's TaskTracker.
+ void RunTask(std::unique_ptr<internal::Task> task,
+ const SequenceToken& sequence_token);
+
+ // Returns true if this TaskScheduler runs its tasks on the current thread.
+ bool RunsTasksOnCurrentThread() const;
+
+ private:
+ // The MessageLoop that runs all tasks posted to this TaskScheduler.
+ MessageLoop message_loop_;
+
+ // The SingleThreadTaskRunner associated with |message_loop_|.
+ const scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_ =
+ message_loop_.task_runner();
+
+ // Handles shutdown behaviors and sets up the environment to run a task.
+ internal::TaskTracker task_tracker_;
+
+#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
+ // Allow usage of FileDescriptorWatcher within the scope of
+ // ScopedTaskScheduler if it runs on a MessageLoopForIO.
+ //
+ // Note: Initializing a single FileDescriptorWatcher for the scope of
+ // ScopedTaskScheduler rather than using TaskTrackerPosix to initialize a
+ // FileDescriptorWatcher in the scope in which tasks run makes it easier to
+ // watch file descriptors from outside of TaskScheduler tasks.
gab 2016/12/08 20:15:45 But doesn't this now give an API to other threads
fdoray 2016/12/09 16:26:41 Removed. Offline discussion: We will stop initial
+ std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_ =
+ message_loop_.IsType(MessageLoop::TYPE_IO)
+ ? MakeUnique<FileDescriptorWatcher>(message_loop_.task_runner())
+ : nullptr;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(TestTaskScheduler);
+};
+
+class TestTaskSchedulerTaskRunner : public SingleThreadTaskRunner {
+ public:
+ TestTaskSchedulerTaskRunner(TestTaskScheduler* task_scheduler,
+ ExecutionMode execution_mode,
+ TaskTraits traits);
+
+ // SingleThreadTaskRunner:
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& closure,
+ TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& closure,
+ TimeDelta delay) override;
+ bool RunsTasksOnCurrentThread() const override;
+
+ private:
+ ~TestTaskSchedulerTaskRunner() override;
+
+ TestTaskScheduler* const task_scheduler_;
+ const ExecutionMode execution_mode_;
+ const SequenceToken sequence_token_;
+ const TaskTraits traits_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTaskSchedulerTaskRunner);
+};
+
+TestTaskScheduler::TestTaskScheduler(ScopedTaskScheduler::Options options)
+ : message_loop_(options & ScopedTaskScheduler::UI_MAIN_LOOP
+ ? MessageLoop::TYPE_UI
+ : MessageLoop::TYPE_IO) {}
+
+TestTaskScheduler::~TestTaskScheduler() {
+ // Prevent the RunUntilIdle() call below from running SKIP_ON_SHUTDOWN and
+ // CONTINUE_ON_SHUTDOWN tasks.
+ task_tracker_.SetHasShutdownStartedForTesting();
+
+ // Run pending BLOCK_SHUTDOWN tasks.
+ RunLoop().RunUntilIdle();
+}
+
+void TestTaskScheduler::PostTaskWithTraits(
+ const tracked_objects::Location& from_here,
+ const TaskTraits& traits,
+ const Closure& task) {
+ CreateTaskRunnerWithTraits(traits)->PostTask(from_here, task);
+}
+
+scoped_refptr<TaskRunner> TestTaskScheduler::CreateTaskRunnerWithTraits(
+ const TaskTraits& traits) {
+ return make_scoped_refptr(
+ new TestTaskSchedulerTaskRunner(this, ExecutionMode::PARALLEL, traits));
+}
+
+scoped_refptr<SequencedTaskRunner>
+TestTaskScheduler::CreateSequencedTaskRunnerWithTraits(
+ const TaskTraits& traits) {
+ return make_scoped_refptr(
+ new TestTaskSchedulerTaskRunner(this, ExecutionMode::SEQUENCED, traits));
+}
- // Create a TaskScheduler with a single thread to make tests deterministic.
- constexpr int kMaxThreads = 1;
- std::vector<SchedulerWorkerPoolParams> worker_pool_params_vector;
- worker_pool_params_vector.emplace_back(
- "Simple", ThreadPriority::NORMAL,
- SchedulerWorkerPoolParams::StandbyThreadPolicy::LAZY, kMaxThreads,
- TimeDelta::Max());
- TaskScheduler::CreateAndSetDefaultTaskScheduler(
- worker_pool_params_vector,
- Bind([](const TaskTraits&) -> size_t { return 0; }));
+scoped_refptr<SingleThreadTaskRunner>
+TestTaskScheduler::CreateSingleThreadTaskRunnerWithTraits(
+ const TaskTraits& traits) {
+ return make_scoped_refptr(new TestTaskSchedulerTaskRunner(
+ this, ExecutionMode::SINGLE_THREADED, traits));
+}
+
+std::vector<const HistogramBase*> TestTaskScheduler::GetHistograms() const {
+ NOTREACHED();
+ return std::vector<const HistogramBase*>();
+}
+
+void TestTaskScheduler::Shutdown() {
+ NOTREACHED();
+}
+
+void TestTaskScheduler::FlushForTesting() {
+ NOTREACHED();
+}
+
+bool TestTaskScheduler::PostTask(std::unique_ptr<internal::Task> task,
+ const SequenceToken& sequence_token) {
+ DCHECK(task);
+ if (!task_tracker_.WillPostTask(task.get()))
+ return false;
+ internal::Task* const task_ptr = task.get();
+ return message_loop_task_runner_->PostDelayedTask(
+ task_ptr->posted_from, Bind(&TestTaskScheduler::RunTask, Unretained(this),
+ Passed(std::move(task)), sequence_token),
+ task_ptr->delay);
+}
+
+void TestTaskScheduler::RunTask(std::unique_ptr<internal::Task> task,
+ const SequenceToken& sequence_token) {
+ // Clear the MessageLoop TaskRunner to allow TaskTracker to register a
+ // Thread/SequencedTaskRunnerHandle as appropriate.
+ message_loop_.SetTaskRunner(nullptr);
+
+ // Run the task.
+ task_tracker_.RunTask(std::move(task), sequence_token.IsValid()
+ ? sequence_token
+ : SequenceToken::Create());
+
+ // Restore the MessageLoop TaskRunner.
+ message_loop_.SetTaskRunner(message_loop_task_runner_);
+}
+
+bool TestTaskScheduler::RunsTasksOnCurrentThread() const {
+ return message_loop_task_runner_->RunsTasksOnCurrentThread();
+}
+
+TestTaskSchedulerTaskRunner::TestTaskSchedulerTaskRunner(
+ TestTaskScheduler* task_scheduler,
+ ExecutionMode execution_mode,
+ TaskTraits traits)
+ : task_scheduler_(task_scheduler),
+ execution_mode_(execution_mode),
+ sequence_token_(execution_mode == ExecutionMode::PARALLEL
+ ? SequenceToken()
+ : SequenceToken::Create()),
+ traits_(traits) {}
+
+bool TestTaskSchedulerTaskRunner::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& closure,
+ TimeDelta delay) {
+ auto task = MakeUnique<internal::Task>(from_here, closure, traits_, delay);
+ if (execution_mode_ == ExecutionMode::SEQUENCED)
+ task->sequenced_task_runner_ref = make_scoped_refptr(this);
+ else if (execution_mode_ == ExecutionMode::SINGLE_THREADED)
+ task->single_thread_task_runner_ref = make_scoped_refptr(this);
+ return task_scheduler_->PostTask(std::move(task), sequence_token_);
+}
+
+bool TestTaskSchedulerTaskRunner::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& closure,
+ TimeDelta delay) {
+ // Tasks are never nested within the task scheduler.
+ return PostDelayedTask(from_here, closure, delay);
+}
+
+bool TestTaskSchedulerTaskRunner::RunsTasksOnCurrentThread() const {
+ if (execution_mode_ == ExecutionMode::PARALLEL)
+ return task_scheduler_->RunsTasksOnCurrentThread();
+ return sequence_token_ == SequenceToken::GetForCurrentThread();
+}
+
+TestTaskSchedulerTaskRunner::~TestTaskSchedulerTaskRunner() = default;
+
+} // namespace
+
+ScopedTaskScheduler::ScopedTaskScheduler()
+ : ScopedTaskScheduler(Options::DEFAULT) {}
+
+ScopedTaskScheduler::ScopedTaskScheduler(Options options) {
+ DCHECK(!TaskScheduler::GetInstance());
+ TaskScheduler::SetInstance(MakeUnique<TestTaskScheduler>(options));
task_scheduler_ = TaskScheduler::GetInstance();
}
ScopedTaskScheduler::~ScopedTaskScheduler() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance());
- TaskScheduler::GetInstance()->Shutdown();
- TaskScheduler::GetInstance()->JoinForTesting();
TaskScheduler::SetInstance(nullptr);
}

Powered by Google App Engine
This is Rietveld 408576698