Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
live_swap_transaction.hpp
Go to the documentation of this file.
1#pragma once
2
26
27#include <exception>
28#include <functional>
29#include <string>
30#include <vector>
31
32namespace pulp::format::reload {
33
38struct SwapStage {
39 std::string name;
40 std::function<bool()> apply;
41 std::function<void()> rollback; // may be null if this stage is always last
42};
43
45 bool ok = false;
46 std::string failed_stage;
47 std::string detail;
48 bool rollback_clean = true;
49};
50
54inline LiveSwapResult apply_live_swap(const std::vector<SwapStage>& stages) {
55 std::vector<const SwapStage*> applied;
56 applied.reserve(stages.size());
57
58 auto unwind = [&](LiveSwapResult result) {
59 // Roll back the applied stages in reverse; a throwing rollback must not
60 // abort the unwind of the others (best-effort; flag it).
61 for (auto it = applied.rbegin(); it != applied.rend(); ++it) {
62 if (!(*it)->rollback) continue;
63 try {
64 (*it)->rollback();
65 } catch (...) {
66 result.rollback_clean = false;
67 }
68 }
69 return result;
70 };
71
72 for (const auto& stage : stages) {
73 bool ok = false;
74 try {
75 ok = stage.apply ? stage.apply() : true;
76 } catch (const std::exception& e) {
77 return unwind({false, stage.name, std::string("threw: ") + e.what(), true});
78 } catch (...) {
79 return unwind({false, stage.name, "threw (non-std)", true});
80 }
81 if (!ok)
82 return unwind({false, stage.name, "stage rejected", true});
83 applied.push_back(&stage);
84 }
85 return {true, "", "", true};
86}
87
102class SwapUnit {
103public:
104 virtual ~SwapUnit() = default;
105
107 virtual std::string name() const = 0;
108
111 virtual SwapStage to_stage() = 0;
112};
113
118inline LiveSwapResult apply_live_swap(const std::vector<SwapUnit*>& units) {
119 std::vector<SwapStage> stages;
120 stages.reserve(units.size());
121 for (auto* unit : units) {
122 if (unit) stages.push_back(unit->to_stage());
123 }
124 return apply_live_swap(stages);
125}
126
127} // namespace pulp::format::reload
The contract a swappable subsystem implements to join a live-swap transaction
Definition live_swap_transaction.hpp:102
virtual SwapStage to_stage()=0
Build the stage for this unit's pending swap, capturing the current state for rollback.
virtual std::string name() const =0
Human-readable identity, surfaced in LiveSwapResult::failed_stage.
Definition build_fingerprint.hpp:23
LiveSwapResult apply_live_swap(const std::vector< SwapStage > &stages)
Apply stages as one transaction.
Definition live_swap_transaction.hpp:54
@ ok
Definition offline_sample_bounce.hpp:20
Definition live_swap_transaction.hpp:44
std::string failed_stage
which stage rejected/threw (empty when ok)
Definition live_swap_transaction.hpp:46
bool ok
Definition live_swap_transaction.hpp:45
bool rollback_clean
false if a rollback() itself threw (best-effort continued)
Definition live_swap_transaction.hpp:48
std::string detail
exception text or "stage rejected"
Definition live_swap_transaction.hpp:47
One half of a live swap.
Definition live_swap_transaction.hpp:38
std::string name
Definition live_swap_transaction.hpp:39
std::function< void()> rollback
Definition live_swap_transaction.hpp:41
std::function< bool()> apply
Definition live_swap_transaction.hpp:40