1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
// 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.
#ifndef COMPONENTS_UNEXPORTABLE_KEYS_BACKGROUND_LONG_TASK_SCHEDULER_H_
#define COMPONENTS_UNEXPORTABLE_KEYS_BACKGROUND_LONG_TASK_SCHEDULER_H_
#include <array>
#include <memory>
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "components/unexportable_keys/background_task_priority.h"
namespace base {
class SequencedTaskRunner;
} // namespace base
namespace unexportable_keys {
class BackgroundTask;
// `BackgroundLongTaskScheduler` allows scheduling `BackgroundTask`s to be run
// on a background thread. It's designed specifically to run long blocking tasks
// that cannot be run in parallel.
//
// The scheduler posts tasks to the background thread one by one to have a
// full control of which task is running next on the main thread. Since the
// tasks being run are long, the risk of running a wrong task outweighs extra
// overhead caused by additional thread hops.
//
// Supported features:
// - Multiple task priorities (defined in background_task_priority.h). Tasks
// with a higher priority are always posted to the background thread before
// tasks with a lower priority.
// Lower-priority tasks are subject to starvation.
// - Dynamic priority changes. Not implemented yet.
// TODO(b/263249728): support dynamic priorities.
// - Task cancellation. A task never runs if it gets cancelled before it's been
// posted on the background thread.
// - Task retries. When it makes sense to retry a task, the scheduler will
// re-add a task to the back of the queue and run it again.
class COMPONENT_EXPORT(UNEXPORTABLE_KEYS) BackgroundLongTaskScheduler {
public:
explicit BackgroundLongTaskScheduler(
scoped_refptr<base::SequencedTaskRunner> background_task_runner);
~BackgroundLongTaskScheduler();
BackgroundLongTaskScheduler(const BackgroundLongTaskScheduler&) = delete;
BackgroundLongTaskScheduler& operator=(const BackgroundLongTaskScheduler&) =
delete;
void PostTask(std::unique_ptr<BackgroundTask> task);
private:
// Type representing a single task queue with a specific priority.
using TaskQueue = base::circular_deque<std::unique_ptr<BackgroundTask>>;
void OnTaskCompleted(BackgroundTask* task);
void MaybeRunNextPendingTask();
TaskQueue& GetTaskQueueForPriority(BackgroundTaskPriority priority);
TaskQueue* GetHighestPriorityNonEmptyTaskQueue();
std::unique_ptr<BackgroundTask> TakeNextPendingTask();
std::array<TaskQueue, kNumTaskPriorities> task_queue_by_priority_;
// `BackgroundTask` that is currently running on `background_task_runner_`.
// It is nullptr if no task is running.
std::unique_ptr<BackgroundTask> running_task_;
// Task runner that has at most one task (`running_task_`) in its queue at any
// moment.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
base::WeakPtrFactory<BackgroundLongTaskScheduler> weak_ptr_factory_{this};
};
} // namespace unexportable_keys
#endif // COMPONENTS_UNEXPORTABLE_KEYS_BACKGROUND_LONG_TASK_SCHEDULER_H_
|