You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
duckstation/src/common/task_queue.h

70 lines
2.1 KiB
C++

// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#pragma once
#include "threading.h"
#include "types.h"
#include <atomic>
#include <condition_variable>
#include <deque>
#include <functional>
#include <mutex>
#include <thread>
#include <vector>
/// Implements a simple task queue with multiple worker threads.
class TaskQueue
{
public:
using TaskFunctionType = std::function<void()>;
TaskQueue();
~TaskQueue();
/// Sets the number of worker threads to be used by the task queue.
/// Setting this to zero threads completes tasks on the calling thread.
/// @param count The desired number of worker threads.
/// @param max_threads The maximum number of worker threads.
void SetWorkerCount(u16 count, u16 max_threads);
/// Returns the number of tasks remaining.
size_t GetOutstandingTasks();
/// Submits a task to the queue for execution.
/// @param func The task function to execute.
void SubmitTask(TaskFunctionType func);
/// Waits for all submitted tasks to complete execution.
void WaitForAll();
/// Executes a single task on the calling thread.
/// Returns false if there was no work to complete.
bool ExecuteOneTask();
private:
/// Waits for all submitted tasks to complete execution.
/// This is a helper function that assumes a lock is already held.
/// @param lock A unique_lock object holding the mutex.
void WaitForAll(std::unique_lock<std::mutex>& lock);
/// Executes one task from the queue.
/// This is a helper function that assumes a lock is already held.
/// @param lock A unique_lock object holding the mutex.
void ExecuteOneTask(std::unique_lock<std::mutex>& lock);
/// Entry point for worker threads. Executes tasks from the queue until termination is signaled.
void WorkerThreadEntryPoint();
std::mutex m_mutex;
std::deque<TaskFunctionType> m_tasks;
size_t m_tasks_outstanding = 0;
u32 m_threads_busy = 0;
u16 m_max_threads = 0;
bool m_threads_done = false;
std::condition_variable m_task_wait_cv;
std::condition_variable m_tasks_done_cv;
std::vector<std::thread> m_threads;
};