Add foundation task queue tests
This commit is contained in:
83
src/foundation/task_queue.cpp
Normal file
83
src/foundation/task_queue.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "foundation/task_queue.h"
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
TaskQueue::TaskQueue(std::size_t max_entries) noexcept
|
||||
: max_entries_(max_entries)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t TaskQueue::size() const noexcept
|
||||
{
|
||||
return tasks_.size();
|
||||
}
|
||||
|
||||
bool TaskQueue::empty() const noexcept
|
||||
{
|
||||
return tasks_.empty();
|
||||
}
|
||||
|
||||
std::size_t TaskQueue::max_entries() const noexcept
|
||||
{
|
||||
return max_entries_;
|
||||
}
|
||||
|
||||
Status TaskQueue::push(TaskItem task)
|
||||
{
|
||||
if (max_entries_ == 0U || max_entries_ > max_task_queue_entries) {
|
||||
return Status::out_of_range("task queue capacity is outside the configured range");
|
||||
}
|
||||
|
||||
if (task.callback == nullptr) {
|
||||
return Status::invalid_argument("task callback must not be null");
|
||||
}
|
||||
|
||||
if (tasks_.size() >= max_entries_) {
|
||||
return Status::out_of_range("task queue is full");
|
||||
}
|
||||
|
||||
tasks_.push_back(task);
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
Result<TaskItem> TaskQueue::pop() noexcept
|
||||
{
|
||||
if (tasks_.empty()) {
|
||||
return Result<TaskItem>::failure(Status::out_of_range("task queue is empty"));
|
||||
}
|
||||
|
||||
const auto task = tasks_.front();
|
||||
tasks_.pop_front();
|
||||
return Result<TaskItem>::success(task);
|
||||
}
|
||||
|
||||
Status TaskQueue::run_next() noexcept
|
||||
{
|
||||
auto task = pop();
|
||||
if (!task.ok()) {
|
||||
return task.status();
|
||||
}
|
||||
|
||||
task.value().callback(task.value().user_data);
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
std::size_t TaskQueue::run_all() noexcept
|
||||
{
|
||||
std::size_t count = 0;
|
||||
while (!tasks_.empty()) {
|
||||
const auto status = run_next();
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void TaskQueue::clear() noexcept
|
||||
{
|
||||
tasks_.clear();
|
||||
}
|
||||
|
||||
}
|
||||
40
src/foundation/task_queue.h
Normal file
40
src/foundation/task_queue.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
constexpr std::size_t max_task_queue_entries = 65536;
|
||||
|
||||
using TaskCallback = void (*)(void* user_data) noexcept;
|
||||
|
||||
struct TaskItem {
|
||||
TaskCallback callback = nullptr;
|
||||
void* user_data = nullptr;
|
||||
std::uint64_t id = 0;
|
||||
};
|
||||
|
||||
class TaskQueue {
|
||||
public:
|
||||
explicit TaskQueue(std::size_t max_entries = max_task_queue_entries) noexcept;
|
||||
|
||||
[[nodiscard]] std::size_t size() const noexcept;
|
||||
[[nodiscard]] bool empty() const noexcept;
|
||||
[[nodiscard]] std::size_t max_entries() const noexcept;
|
||||
|
||||
[[nodiscard]] Status push(TaskItem task);
|
||||
[[nodiscard]] Result<TaskItem> pop() noexcept;
|
||||
[[nodiscard]] Status run_next() noexcept;
|
||||
[[nodiscard]] std::size_t run_all() noexcept;
|
||||
void clear() noexcept;
|
||||
|
||||
private:
|
||||
std::size_t max_entries_ = max_task_queue_entries;
|
||||
std::deque<TaskItem> tasks_;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user