chromium/services/accessibility/features/devtools/debug_command_queue.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/accessibility/features/devtools/debug_command_queue.h"

#include "base/task/sequenced_task_runner.h"

namespace ax {

DebugCommandQueue::DebugCommandQueue()
    : v8_runner_(base::SequencedTaskRunner::GetCurrentDefault()),
      wake_up_(&lock_) {}

DebugCommandQueue::~DebugCommandQueue() = default;

void DebugCommandQueue::QuitPauseForDebugger() {
  // Can be called from any thread.
  base::AutoLock auto_lock(lock_);
  wake_up_.Signal();
}

void DebugCommandQueue::QueueTaskForV8Thread(base::OnceClosure task) {
  DCHECK(task);
  // Can be called from any thread.
  base::AutoLock auto_lock(lock_);
  queue_.push(std::move(task));
  v8_runner_->PostTask(FROM_HERE,
                       base::BindOnce(&DebugCommandQueue::RunQueue, this));
}

void DebugCommandQueue::RunQueue() {
  DCHECK(v8_runner_->RunsTasksInCurrentSequence());
  // Note: one of commands in the queue can cause PauseForDebuggerAndRunCommands
  // to be entered. This is OK since we pull tasks off one-by-one and run them
  // w/o a lock held.
  base::AutoLock auto_lock(lock_);
  RunQueueWithLockHeld();
}

void DebugCommandQueue::RunQueueWithLockHeld() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
  DCHECK(v8_runner_->RunsTasksInCurrentSequence());
  while (!queue_.empty()) {
    base::OnceClosure to_run = std::move(queue_.front());
    queue_.pop();
    {
      // Relinquish lock for running callback.
      base::AutoUnlock temporary_unlock(lock_);
      std::move(to_run).Run();
    }
  }
}

}  // namespace ax