Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
budget_policy.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <cstdint>
7#include <limits>
8
9namespace pulp::runtime {
10
17
18enum class RuntimeBudgetAction : std::uint8_t {
19 Run = 0,
23};
24
30
38
41 const char* reason = "within-budget";
42
43 bool should_run() const noexcept { return action == RuntimeBudgetAction::Run; }
44};
45
47 std::uint32_t run_count = 0;
48 std::uint32_t defer_count = 0;
49 std::uint32_t shed_count = 0;
50 std::uint32_t bypass_count = 0;
51 std::uint64_t consumed_budget = 0;
52 std::uint64_t remaining_budget = 0;
53};
54
55inline const char* to_string(RuntimeBudgetAction action) noexcept {
56 switch (action) {
57 case RuntimeBudgetAction::Run: return "run";
58 case RuntimeBudgetAction::Defer: return "defer";
59 case RuntimeBudgetAction::Shed: return "shed";
60 case RuntimeBudgetAction::Bypass: return "bypass";
61 }
62 return "bypass";
63}
64
66 const RuntimeBudgetRequest& request,
67 const RuntimeBudgetPolicy& policy = {}) noexcept {
68 if (request.lane == RuntimeWorkLane::CriticalAudio) {
69 return {RuntimeBudgetAction::Run, "critical-audio"};
70 }
71
72 if (request.overload_active) {
74 && policy.shed_opportunistic_on_overload) {
75 return {RuntimeBudgetAction::Shed, "overload-shed-opportunistic"};
76 }
78 && policy.shed_background_on_overload) {
79 return {RuntimeBudgetAction::Shed, "overload-shed-background"};
80 }
81 }
82
83 const std::uint64_t reserve =
85 ? policy.critical_audio_reserve
86 : 0;
87 const bool has_budget =
88 request.remaining_budget >= reserve
89 && request.estimated_cost <= request.remaining_budget - reserve;
90
91 if (has_budget) return {RuntimeBudgetAction::Run, "within-budget"};
92
93 if (request.required) return {RuntimeBudgetAction::Defer, "required-defer"};
95 return {RuntimeBudgetAction::Defer, "interactive-defer"};
97 return {RuntimeBudgetAction::Shed, "budget-shed-opportunistic"};
98 return {RuntimeBudgetAction::Bypass, "budget-bypass-background"};
99}
100
102public:
103 explicit RuntimeBudgetFrame(std::uint64_t budget,
105 bool overload_active = false) noexcept
106 : policy_(policy)
107 , remaining_budget_(budget)
108 , overload_active_(overload_active) {
109 stats_.remaining_budget = remaining_budget_;
110 }
111
113 std::uint64_t estimated_cost,
114 bool required = false) noexcept {
115 RuntimeBudgetRequest request;
116 request.lane = lane;
117 request.estimated_cost = estimated_cost;
118 request.remaining_budget = remaining_budget_;
119 request.required = required;
120 request.overload_active = overload_active_;
121
122 const auto decision = evaluate_runtime_budget(request, policy_);
123 record(decision.action, estimated_cost);
124 return decision;
125 }
126
127 std::uint64_t remaining_budget() const noexcept { return remaining_budget_; }
128 bool overload_active() const noexcept { return overload_active_; }
129 const RuntimeBudgetPolicy& policy() const noexcept { return policy_; }
130 const RuntimeBudgetFrameStats& stats() const noexcept { return stats_; }
131
132 void set_overload_active(bool active) noexcept { overload_active_ = active; }
133
134 void add_budget(std::uint64_t budget) noexcept {
135 const auto previous = remaining_budget_;
136 remaining_budget_ += budget;
137 if (remaining_budget_ < previous) {
138 remaining_budget_ = std::numeric_limits<std::uint64_t>::max();
139 }
140 stats_.remaining_budget = remaining_budget_;
141 }
142
143private:
144 void record(RuntimeBudgetAction action, std::uint64_t estimated_cost) noexcept {
145 switch (action) {
147 ++stats_.run_count;
148 if (stats_.consumed_budget
149 > std::numeric_limits<std::uint64_t>::max() - estimated_cost) {
150 stats_.consumed_budget = std::numeric_limits<std::uint64_t>::max();
151 } else {
152 stats_.consumed_budget += estimated_cost;
153 }
154 if (remaining_budget_ >= estimated_cost) {
155 remaining_budget_ -= estimated_cost;
156 } else {
157 remaining_budget_ = 0;
158 }
159 break;
161 ++stats_.defer_count;
162 break;
164 ++stats_.shed_count;
165 break;
167 ++stats_.bypass_count;
168 break;
169 }
170 stats_.remaining_budget = remaining_budget_;
171 }
172
173 RuntimeBudgetPolicy policy_{};
174 std::uint64_t remaining_budget_ = 0;
175 bool overload_active_ = false;
176 RuntimeBudgetFrameStats stats_{};
177};
178
179} // namespace pulp::runtime
std::uint64_t remaining_budget() const noexcept
Definition budget_policy.hpp:127
void set_overload_active(bool active) noexcept
Definition budget_policy.hpp:132
bool overload_active() const noexcept
Definition budget_policy.hpp:128
RuntimeBudgetDecision evaluate(RuntimeWorkLane lane, std::uint64_t estimated_cost, bool required=false) noexcept
Definition budget_policy.hpp:112
const RuntimeBudgetFrameStats & stats() const noexcept
Definition budget_policy.hpp:130
void add_budget(std::uint64_t budget) noexcept
Definition budget_policy.hpp:134
RuntimeBudgetFrame(std::uint64_t budget, RuntimeBudgetPolicy policy={}, bool overload_active=false) noexcept
Definition budget_policy.hpp:103
const RuntimeBudgetPolicy & policy() const noexcept
Definition budget_policy.hpp:129
void request(Permission p, RequestCallback cb)
Async request.
Definition generated_event_source.hpp:33
RuntimeBudgetAction
Definition budget_policy.hpp:18
@ Bypass
Definition budget_policy.hpp:22
@ Defer
Definition budget_policy.hpp:20
@ Run
Definition budget_policy.hpp:19
@ Shed
Definition budget_policy.hpp:21
RuntimeBudgetDecision evaluate_runtime_budget(const RuntimeBudgetRequest &request, const RuntimeBudgetPolicy &policy={}) noexcept
Definition budget_policy.hpp:65
const char * to_string(RuntimeBudgetAction action) noexcept
Definition budget_policy.hpp:55
RuntimeWorkLane
Definition budget_policy.hpp:11
@ Interactive
Definition budget_policy.hpp:13
@ Opportunistic
Definition budget_policy.hpp:15
@ Background
Definition budget_policy.hpp:14
@ CriticalAudio
Definition budget_policy.hpp:12
Definition budget_policy.hpp:39
RuntimeBudgetAction action
Definition budget_policy.hpp:40
bool should_run() const noexcept
Definition budget_policy.hpp:43
const char * reason
Definition budget_policy.hpp:41
Definition budget_policy.hpp:46
std::uint64_t consumed_budget
Definition budget_policy.hpp:51
std::uint32_t shed_count
Definition budget_policy.hpp:49
std::uint64_t remaining_budget
Definition budget_policy.hpp:52
std::uint32_t bypass_count
Definition budget_policy.hpp:50
std::uint32_t run_count
Definition budget_policy.hpp:47
std::uint32_t defer_count
Definition budget_policy.hpp:48
Definition budget_policy.hpp:25
bool shed_opportunistic_on_overload
Definition budget_policy.hpp:28
std::uint64_t critical_audio_reserve
Definition budget_policy.hpp:26
bool shed_background_on_overload
Definition budget_policy.hpp:27
Definition budget_policy.hpp:31
std::uint64_t estimated_cost
Definition budget_policy.hpp:33
bool required
Definition budget_policy.hpp:35
RuntimeWorkLane lane
Definition budget_policy.hpp:32
bool overload_active
Definition budget_policy.hpp:36
std::uint64_t remaining_budget
Definition budget_policy.hpp:34