| /* | 
 |  * Copyright (C) 2017 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include "src/base/test/test_task_runner.h" | 
 |  | 
 | #include <stdio.h> | 
 |  | 
 | #include <chrono> | 
 |  | 
 | #include "perfetto/base/logging.h" | 
 |  | 
 | namespace perfetto { | 
 | namespace base { | 
 |  | 
 | TestTaskRunner::TestTaskRunner() = default; | 
 |  | 
 | TestTaskRunner::~TestTaskRunner() = default; | 
 |  | 
 | void TestTaskRunner::Run() { | 
 |   PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |   for (;;) | 
 |     task_runner_.Run(); | 
 | } | 
 |  | 
 | void TestTaskRunner::RunUntilIdle() { | 
 |   PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |   task_runner_.PostTask(std::bind(&TestTaskRunner::QuitIfIdle, this)); | 
 |   task_runner_.Run(); | 
 | } | 
 |  | 
 | void TestTaskRunner::QuitIfIdle() { | 
 |   PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |   if (task_runner_.IsIdleForTesting()) { | 
 |     task_runner_.Quit(); | 
 |     return; | 
 |   } | 
 |   task_runner_.PostTask(std::bind(&TestTaskRunner::QuitIfIdle, this)); | 
 | } | 
 |  | 
 | void TestTaskRunner::RunUntilCheckpoint(const std::string& checkpoint, | 
 |                                         uint32_t timeout_ms) { | 
 |   PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |   if (checkpoints_.count(checkpoint) == 0) { | 
 |     PERFETTO_FATAL("[TestTaskRunner] Checkpoint \"%s\" does not exist.\n", | 
 |                    checkpoint.c_str()); | 
 |   } | 
 |   if (checkpoints_[checkpoint]) | 
 |     return; | 
 |  | 
 |   task_runner_.PostDelayedTask( | 
 |       [this, checkpoint] { | 
 |         if (checkpoints_[checkpoint]) | 
 |           return; | 
 |         PERFETTO_FATAL("[TestTaskRunner] Failed to reach checkpoint \"%s\"\n", | 
 |                        checkpoint.c_str()); | 
 |       }, | 
 |       timeout_ms); | 
 |  | 
 |   pending_checkpoint_ = checkpoint; | 
 |   task_runner_.Run(); | 
 | } | 
 |  | 
 | std::function<void()> TestTaskRunner::CreateCheckpoint( | 
 |     const std::string& checkpoint) { | 
 |   PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |   PERFETTO_DCHECK(checkpoints_.count(checkpoint) == 0); | 
 |   auto checkpoint_iter = checkpoints_.emplace(checkpoint, false); | 
 |   return [this, checkpoint_iter] { | 
 |     PERFETTO_DCHECK_THREAD(thread_checker_); | 
 |     checkpoint_iter.first->second = true; | 
 |     if (pending_checkpoint_ == checkpoint_iter.first->first) { | 
 |       pending_checkpoint_.clear(); | 
 |       task_runner_.Quit(); | 
 |     } | 
 |   }; | 
 | } | 
 |  | 
 | // TaskRunner implementation. | 
 | void TestTaskRunner::PostTask(std::function<void()> closure) { | 
 |   task_runner_.PostTask(std::move(closure)); | 
 | } | 
 |  | 
 | void TestTaskRunner::PostDelayedTask(std::function<void()> closure, | 
 |                                      uint32_t delay_ms) { | 
 |   task_runner_.PostDelayedTask(std::move(closure), delay_ms); | 
 | } | 
 |  | 
 | void TestTaskRunner::AddFileDescriptorWatch(PlatformHandle fd, | 
 |                                             std::function<void()> callback) { | 
 |   task_runner_.AddFileDescriptorWatch(fd, std::move(callback)); | 
 | } | 
 |  | 
 | void TestTaskRunner::RemoveFileDescriptorWatch(PlatformHandle fd) { | 
 |   task_runner_.RemoveFileDescriptorWatch(fd); | 
 | } | 
 |  | 
 | bool TestTaskRunner::RunsTasksOnCurrentThread() const { | 
 |   return task_runner_.RunsTasksOnCurrentThread(); | 
 | } | 
 |  | 
 | }  // namespace base | 
 | }  // namespace perfetto |