Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
background_task_lane.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <chrono>
5#include <cstddef>
6#include <cstdint>
7#include <thread>
8#include <type_traits>
9#include <utility>
10
15
16namespace pulp::format {
17
19
30template <typename Task, std::size_t Capacity = 64>
32 static_assert(std::is_trivially_copyable_v<Task>,
33 "RT task payloads must be trivially copyable");
34public:
35 using Handler = void (*)(void*, const Task&);
36 using HandlerFunction = runtime::FixedFunction<void(const Task&), 48>;
37
38 BackgroundTaskLane() = default;
42
43 bool start(Handler handler, void* context = nullptr,
45 if (!handler)
46 return false;
47 return start(
48 HandlerFunction([handler, context](const Task& task) { handler(context, task); }),
49 policy);
50 }
51
52 bool start(HandlerFunction handler,
54 if (!handler || running_.load(std::memory_order_acquire)) return false;
55 handler_ = std::move(handler);
56 policy_ = policy;
57 latest_generation_.store(0, std::memory_order_relaxed);
58 stopping_.store(false, std::memory_order_release);
59 PULP_TRY {
60 worker_ = std::thread([this] { worker_loop(); });
62 handler_.reset();
63 return false;
64 }
65 running_.store(true, std::memory_order_release);
66 return true;
67 }
68
69 void stop() noexcept {
70 stopping_.store(true, std::memory_order_release);
71 if (worker_.joinable()) worker_.join();
72 running_.store(false, std::memory_order_release);
73 }
74
75 bool try_spawn(const Task& task) noexcept {
76 if (!running_.load(std::memory_order_acquire)) return false;
77 if (policy_ == BackgroundTaskPolicy::Latest) {
78 latest_.write(task);
79 latest_generation_.fetch_add(1, std::memory_order_release);
80 return true;
81 }
82 return ordered_.try_push(task);
83 }
84
85 bool running() const noexcept { return running_.load(std::memory_order_acquire); }
86 std::uint64_t overflow_count() const noexcept { return ordered_.overflow_count(); }
87
88private:
89 void worker_loop() noexcept {
90 std::uint64_t consumed_generation = 0;
91 while (!stopping_.load(std::memory_order_acquire)) {
92 bool handled = false;
93 if (policy_ == BackgroundTaskPolicy::Latest) {
94 const auto generation = latest_generation_.load(std::memory_order_acquire);
95 if (generation != consumed_generation) {
96 invoke(latest_.read());
97 consumed_generation = generation;
98 handled = true;
99 }
100 } else if (auto task = ordered_.try_pop()) {
101 invoke(*task);
102 handled = true;
103 }
104 if (!handled) std::this_thread::sleep_for(std::chrono::milliseconds(1));
105 }
106 if (policy_ == BackgroundTaskPolicy::Ordered) {
107 while (auto task = ordered_.try_pop()) invoke(*task);
108 } else {
109 const auto generation = latest_generation_.load(std::memory_order_acquire);
110 if (generation != consumed_generation) invoke(latest_.read());
111 }
112 }
113
114 void invoke(const Task& task) noexcept {
115 PULP_TRY {
116 handler_(task);
117 }
119 }
120
121 runtime::SpscQueue<Task, Capacity> ordered_;
122 runtime::TripleBuffer<Task> latest_;
123 std::atomic<std::uint64_t> latest_generation_{0};
124 std::atomic<bool> running_{false};
125 std::atomic<bool> stopping_{false};
126 HandlerFunction handler_;
128 std::thread worker_;
129};
130
131} // namespace pulp::format
std::uint64_t overflow_count() const noexcept
Definition background_task_lane.hpp:86
bool start(HandlerFunction handler, BackgroundTaskPolicy policy=BackgroundTaskPolicy::Ordered)
Definition background_task_lane.hpp:52
BackgroundTaskLane(const BackgroundTaskLane &)=delete
runtime::FixedFunction< void(const Task &), 48 > HandlerFunction
Definition background_task_lane.hpp:36
~BackgroundTaskLane()
Definition background_task_lane.hpp:39
bool try_spawn(const Task &task) noexcept
Definition background_task_lane.hpp:75
bool running() const noexcept
Definition background_task_lane.hpp:85
BackgroundTaskLane & operator=(const BackgroundTaskLane &)=delete
void(*)(void *, const Task &) Handler
Definition background_task_lane.hpp:35
bool start(Handler handler, void *context=nullptr, BackgroundTaskPolicy policy=BackgroundTaskPolicy::Ordered)
Definition background_task_lane.hpp:43
void stop() noexcept
Definition background_task_lane.hpp:69
Definition fixed_function.hpp:42
const T & read() noexcept
Read the latest published value from the reader thread.
Definition triple_buffer.hpp:88
Portable try/catch macros for source that must also compile with C++ exceptions disabled (-fno-except...
#define PULP_TRY
Definition exceptions.hpp:42
#define PULP_CATCH_ALL
Definition exceptions.hpp:43
FixedFunction<Signature, Capacity> - a move-only callable wrapper with inline storage that never touc...
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
BackgroundTaskPolicy
Definition background_task_lane.hpp:18
@ Ordered
Definition background_task_lane.hpp:18
@ Latest
Definition background_task_lane.hpp:18
Lock-free latest-value publication between two threads.