threadman 0.1.0
Header-only C++23 managed threads, dynamic pools, futures, and executors
Loading...
Searching...
No Matches
task.hpp
Go to the documentation of this file.
1#pragma once
2
15
16#include <threadman/display.hpp>
17#include <threadman/stats.hpp>
18
19#include <commons/display_info.hpp>
20
21#include <atomic>
22#include <chrono>
23#include <cstdint>
24#include <exception>
25#include <memory>
26#include <mutex>
27#include <optional>
28#include <string>
29#include <utility>
30
31namespace threadman {
32
34public:
37 struct State {
38 std::uint64_t id = 0;
39 std::optional<std::string> name;
40 std::uint64_t pool_id = 0;
41 std::atomic<TaskState> state{TaskState::Queued};
42 std::chrono::steady_clock::time_point created_at{std::chrono::steady_clock::now()};
43 std::optional<std::chrono::steady_clock::time_point> started_at;
44 std::optional<std::chrono::steady_clock::time_point> finished_at;
45 std::exception_ptr exception;
46 mutable std::mutex mtx; // guards optionals + exception
47 };
48
50 explicit TaskHandle(const std::uint64_t id,
51 const std::uint64_t pool_id,
52 std::optional<std::string> name = std::nullopt)
53 : state_(std::make_shared<State>()) {
54 state_->id = id;
55 state_->pool_id = pool_id;
56 state_->name = std::move(name);
57 }
58
59 TaskHandle() = default;
60 TaskHandle(const TaskHandle&) = default;
61 TaskHandle(TaskHandle&&) noexcept = default;
62 TaskHandle& operator=(const TaskHandle&) = default;
63 TaskHandle& operator=(TaskHandle&&) noexcept = default;
64 ~TaskHandle() = default;
65
67 [[nodiscard]] bool valid() const noexcept {
68 return static_cast<bool>(state_);
69 }
70
71 [[nodiscard]] std::uint64_t id() const noexcept {
72 return state_ ? state_->id : 0;
73 }
74 [[nodiscard]] std::uint64_t pool_id() const noexcept {
75 return state_ ? state_->pool_id : 0;
76 }
77 [[nodiscard]] TaskState state() const noexcept {
78 return state_ ? state_->state.load(std::memory_order_acquire) : TaskState::Cancelled;
79 }
80 [[nodiscard]] std::optional<std::string> name() const {
81 if (!state_) {
82 return std::nullopt;
83 }
84 std::scoped_lock guard(state_->mtx);
85 return state_->name;
86 }
87
89 [[nodiscard]] std::shared_ptr<State> raw() const noexcept {
90 return state_;
91 }
92
94 void mark_running() const {
95 if (!state_) {
96 return;
97 }
98 {
99 const auto now = std::chrono::steady_clock::now();
100 std::scoped_lock guard(state_->mtx);
101 state_->started_at = now;
102 }
103 state_->state.store(TaskState::Running, std::memory_order_release);
104 }
105
107 void mark_completed() const {
108 if (!state_) {
109 return;
110 }
111 {
112 const auto now = std::chrono::steady_clock::now();
113 std::scoped_lock guard(state_->mtx);
114 state_->finished_at = now;
115 }
116 state_->state.store(TaskState::Completed, std::memory_order_release);
117 }
118
122 void mark_failed(const std::exception_ptr& ex) const {
123 if (!state_) {
124 return;
125 }
126 {
127 const auto now = std::chrono::steady_clock::now();
128 std::scoped_lock guard(state_->mtx);
129 state_->finished_at = now;
130 state_->exception = ex;
131 }
132 state_->state.store(TaskState::Failed, std::memory_order_release);
133 }
134
136 void mark_cancelled(const std::exception_ptr& ex = nullptr) const {
137 if (!state_) {
138 return;
139 }
140 {
141 const auto now = std::chrono::steady_clock::now();
142 std::scoped_lock guard(state_->mtx);
143 state_->finished_at = now;
144 if (ex) {
145 state_->exception = ex;
146 }
147 }
148 state_->state.store(TaskState::Cancelled, std::memory_order_release);
149 }
150
152 [[nodiscard]] TaskSnapshot snapshot() const {
153 TaskSnapshot snap;
154 if (!state_) {
155 return snap;
156 }
157 snap.id = state_->id;
158 snap.pool_id = state_->pool_id;
159 snap.state = state_->state.load(std::memory_order_acquire);
160 snap.failed = (snap.state == TaskState::Failed);
161 std::scoped_lock guard(state_->mtx);
162 snap.name = state_->name;
163 snap.created_at = state_->created_at;
164 snap.started_at = state_->started_at;
165 snap.finished_at = state_->finished_at;
166 return snap;
167 }
168
169 [[nodiscard]] static const comms::DisplayInfo& display_info() {
170 static const comms::DisplayInfo info{
171 .name = "TaskHandle",
172 .description = "Handle to a single task submitted to a ThreadPool.",
173 .icon = comms::Icon::from("mdi:format-list-checks"),
174 };
175 return info;
176 }
177
178private:
179 std::shared_ptr<State> state_;
180};
181
182} // namespace threadman
Definition task.hpp:33
void mark_completed() const
Transition Running → Completed and stamp finished_at = now.
Definition task.hpp:107
TaskHandle(const TaskHandle &)=default
void mark_running() const
Transition Queued → Running and stamp started_at = now.
Definition task.hpp:94
std::uint64_t id() const noexcept
Definition task.hpp:71
TaskSnapshot snapshot() const
Consistent snapshot of the task's state.
Definition task.hpp:152
TaskHandle(TaskHandle &&) noexcept=default
TaskState state() const noexcept
Definition task.hpp:77
static const comms::DisplayInfo & display_info()
Definition task.hpp:169
void mark_failed(const std::exception_ptr &ex) const
Transition Running → Failed and stamp finished_at = now.
Definition task.hpp:122
std::shared_ptr< State > raw() const noexcept
Direct access to the shared state; used by the pool/future internals.
Definition task.hpp:89
std::optional< std::string > name() const
Definition task.hpp:80
std::uint64_t pool_id() const noexcept
Definition task.hpp:74
void mark_cancelled(const std::exception_ptr &ex=nullptr) const
Transition any non-terminal state → Cancelled and stamp finished_at.
Definition task.hpp:136
TaskHandle(const std::uint64_t id, const std::uint64_t pool_id, std::optional< std::string > name=std::nullopt)
Construct a handle owning a freshly-allocated State.
Definition task.hpp:50
bool valid() const noexcept
True iff this handle owns a state.
Definition task.hpp:67
Re-export <commons/display_info.hpp> and attach non-intrusive comms::HasDisplayInfo<> specializations...
Definition exceptions.hpp:22
TaskState
Lifecycle state of a TaskHandle.
Definition stats.hpp:31
@ Completed
Body returned normally.
@ Running
Picked up by a worker; body executing.
@ Queued
Submitted, waiting for a worker.
@ Cancelled
Discarded before running (shutdown_now, etc.).
@ Failed
Body threw.
Plain value snapshots of the live state of the ThreadMan world — threads, pools, tasks,...
Heap-resident bookkeeping for a single task.
Definition task.hpp:37
std::mutex mtx
Definition task.hpp:46
std::exception_ptr exception
Definition task.hpp:45
std::optional< std::chrono::steady_clock::time_point > finished_at
Definition task.hpp:44
std::chrono::steady_clock::time_point created_at
Definition task.hpp:42
std::optional< std::string > name
Definition task.hpp:39
std::uint64_t pool_id
Definition task.hpp:40
std::optional< std::chrono::steady_clock::time_point > started_at
Definition task.hpp:43
std::atomic< TaskState > state
Definition task.hpp:41
A snapshot of a single task's lifecycle.
Definition stats.hpp:79
std::chrono::steady_clock::time_point created_at
Definition stats.hpp:84
std::optional< std::chrono::steady_clock::time_point > finished_at
Definition stats.hpp:86
std::uint64_t pool_id
Definition stats.hpp:82
std::optional< std::string > name
Definition stats.hpp:81
TaskState state
Definition stats.hpp:83
std::uint64_t id
Definition stats.hpp:80
std::optional< std::chrono::steady_clock::time_point > started_at
Definition stats.hpp:85
bool failed
Definition stats.hpp:87