Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
jthread_compat.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
24#include <kcenon/common/config/feature_flags.h>
25#include <atomic>
26#include <condition_variable>
27#include <functional>
28#include <mutex>
29#include <thread>
30
31#if KCENON_HAS_JTHREAD
32 #include <stop_token>
33#endif
34
35// Legacy alias for backward compatibility
36#ifndef LOGGER_HAS_JTHREAD
37 #define LOGGER_HAS_JTHREAD KCENON_HAS_JTHREAD
38#endif
39
40namespace kcenon::logger::async {
41
49public:
51
55 void request_stop() {
56 stopped_.store(true, std::memory_order_release);
57 }
58
62 [[nodiscard]] bool stop_requested() const noexcept {
63 return stopped_.load(std::memory_order_acquire);
64 }
65
69 void reset() {
70 stopped_.store(false, std::memory_order_release);
71 }
72
73private:
74 std::atomic<bool> stopped_;
75};
76
85public:
89 compat_jthread() noexcept = default;
90
100#if KCENON_HAS_JTHREAD
101 template<typename F>
102 explicit compat_jthread(F&& func)
103 : thread_(std::forward<F>(func)) {}
104#else
105 template<typename F>
106 explicit compat_jthread(F&& func)
107 : stop_source_(std::make_shared<simple_stop_source>())
108 , thread_([func = std::forward<F>(func), stop = stop_source_]() {
109 func(*stop);
110 }) {}
111#endif
112
117 if (joinable()) {
118 request_stop();
119 join();
120 }
121 }
122
123 // Non-copyable
126
127 // Movable
129#if KCENON_HAS_JTHREAD
130 : thread_(std::move(other.thread_)) {}
131#else
132 : stop_source_(std::move(other.stop_source_))
133 , thread_(std::move(other.thread_)) {}
134#endif
135
137 if (this != &other) {
138 if (joinable()) {
139 request_stop();
140 join();
141 }
142#if KCENON_HAS_JTHREAD
143 thread_ = std::move(other.thread_);
144#else
145 stop_source_ = std::move(other.stop_source_);
146 thread_ = std::move(other.thread_);
147#endif
148 }
149 return *this;
150 }
151
155 [[nodiscard]] bool joinable() const noexcept {
156#if KCENON_HAS_JTHREAD
157 return thread_.joinable();
158#else
159 return thread_.joinable();
160#endif
161 }
162
167#if KCENON_HAS_JTHREAD
168 thread_.request_stop();
169#else
170 if (stop_source_) {
171 stop_source_->request_stop();
172 }
173#endif
174 }
175
179 void join() {
180#if KCENON_HAS_JTHREAD
181 if (thread_.joinable()) {
182 thread_.join();
183 }
184#else
185 if (thread_.joinable()) {
186 thread_.join();
187 }
188#endif
189 }
190
191#if !KCENON_HAS_JTHREAD
200 [[nodiscard]] std::shared_ptr<simple_stop_source> get_stop_source() const noexcept {
201 return stop_source_;
202 }
203#endif
204
205private:
206#if KCENON_HAS_JTHREAD
207 std::jthread thread_;
208#else
209 std::shared_ptr<simple_stop_source> stop_source_;
210 std::thread thread_;
211#endif
212};
213
221public:
232#if KCENON_HAS_JTHREAD
233 template<typename Lock, typename Predicate>
234 static bool wait(std::condition_variable_any& cv,
235 Lock& lock,
236 std::stop_token stop,
237 Predicate pred) {
238 return cv.wait(lock, stop, pred);
239 }
240#else
241 template<typename Lock, typename Predicate>
242 static bool wait(std::condition_variable& cv,
243 Lock& lock,
244 simple_stop_source& stop,
245 Predicate pred) {
246 cv.wait(lock, [&]() {
247 return stop.stop_requested() || pred();
248 });
249 return !stop.stop_requested() && pred();
250 }
251#endif
252};
253
254} // namespace kcenon::logger::async
Condition variable wait helper with stop support.
static bool wait(std::condition_variable &cv, Lock &lock, simple_stop_source &stop, Predicate pred)
Wait on condition variable with stop support.
Wrapper for std::jthread or std::thread with manual stop mechanism.
std::shared_ptr< simple_stop_source > get_stop_source() const noexcept
Get the stop source (fallback mode only)
compat_jthread & operator=(compat_jthread &&other) noexcept
compat_jthread(F &&func)
Construct and start thread with stop token support.
std::shared_ptr< simple_stop_source > stop_source_
~compat_jthread()
Destructor - requests stop and joins.
bool joinable() const noexcept
Check if thread is joinable.
compat_jthread(const compat_jthread &)=delete
void request_stop()
Request the thread to stop.
compat_jthread & operator=(const compat_jthread &)=delete
void join()
Wait for thread to complete.
compat_jthread() noexcept=default
Default constructor - no thread.
compat_jthread(compat_jthread &&other) noexcept
Simple stop source for environments without std::stop_token.
bool stop_requested() const noexcept
Check if stop was requested.
void reset()
Reset stop state (for reuse)