Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
sample_stream_service.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <atomic>
9#include <cstddef>
10#include <cstdint>
11#include <memory>
12#include <optional>
13#include <type_traits>
14#include <vector>
15
16namespace pulp::audio {
17
19 std::uint64_t source_id = 0;
20 std::uint64_t source_generation = 0;
21};
22
24 std::uint64_t requester_id = 0;
25 std::uint64_t requester_generation = 0;
26};
27
43
46 std::uint32_t channels = 0;
47 std::uint64_t total_frames = 0;
48 std::uint64_t page_frames = 0;
49 std::uint32_t cache_page_count = 0;
50};
51
60
66
73
74static_assert(std::is_trivially_copyable_v<SampleStreamCommand>);
75
76enum class SampleStreamCommandPushStatus : std::uint8_t {
79};
80
82 std::size_t pending = 0;
83 std::size_t capacity = 0;
84 std::uint64_t overflow_count = 0;
85};
86
90template<std::size_t Capacity>
92public:
94 const SampleStreamPageDemand& demand) noexcept {
95 return push({
97 .demand = demand,
98 });
99 }
100
102 SampleStreamRequesterToken requester) noexcept {
103 return push({
105 .requester = requester,
106 });
107 }
108
110 SampleStreamSourceToken source) noexcept {
111 return push({
113 .source = source,
114 });
115 }
116
118 const auto queue = queue_.telemetry();
119 return {
120 .pending = queue.size_approx,
121 .capacity = queue.capacity,
122 .overflow_count = queue.overflow_count,
123 };
124 }
125
126 static constexpr std::size_t capacity() noexcept { return Capacity; }
127
128private:
130
131 SampleStreamCommandPushStatus push(const SampleStreamCommand& command) noexcept {
132 return queue_.try_push(command) ? SampleStreamCommandPushStatus::Enqueued
134 }
135
136 std::optional<SampleStreamCommand> try_pop() noexcept {
137 return queue_.try_pop();
138 }
139
141};
142
144 std::size_t commands_drained = 0;
145 std::size_t demand_commands = 0;
148 std::size_t demands_inserted = 0;
149 std::size_t demands_refreshed = 0;
150 std::size_t demands_rejected_full = 0;
151 std::size_t demands_invalid = 0;
152 std::size_t requests_cancelled = 0;
153};
154
156struct SampleStreamCacheServiceTestAccess;
157
159public:
161
163 const SampleStreamWindow* window,
164 std::uint64_t total_frames,
165 std::uint64_t page_frames,
166 std::uint64_t registration_epoch) const noexcept {
167 return window_ != nullptr && window_ == window &&
168 source_id_ == token.source_id &&
169 source_generation_ == token.source_generation &&
170 total_frames_ == total_frames && page_frames_ == page_frames &&
171 registration_epoch_ == registration_epoch;
172 }
173
174private:
176
178 const SampleStreamWindow* window,
179 std::uint64_t total_frames,
180 std::uint64_t page_frames,
181 std::uint64_t registration_epoch) noexcept
182 : window_(window),
183 source_id_(token.source_id),
184 source_generation_(token.source_generation),
185 total_frames_(total_frames),
186 page_frames_(page_frames),
187 registration_epoch_(registration_epoch) {}
188
189 const SampleStreamWindow* window_ = nullptr;
190 std::uint64_t source_id_ = 0;
191 std::uint64_t source_generation_ = 0;
192 std::uint64_t total_frames_ = 0;
193 std::uint64_t page_frames_ = 0;
194 std::uint64_t registration_epoch_ = 0;
195};
196
197static_assert(std::is_trivially_copyable_v<SampleStreamSourceRegistrationProof>);
198static_assert(std::is_standard_layout_v<SampleStreamSourceRegistrationProof>);
199
203 std::uint64_t total_frames = 0;
204 std::uint64_t page_frames = 0;
205 std::uint64_t registration_epoch = 0;
208
209 bool valid() const noexcept {
210 return token.source_id != 0 && token.source_generation != 0 &&
211 window != nullptr && total_frames != 0 && page_frames != 0 &&
212 memory_governor_epoch.valid() &&
213 registration.matches(token,
214 window,
218 }
219};
220
221static_assert(std::is_trivially_copyable_v<SampleStreamCacheSourceView>);
222static_assert(std::is_standard_layout_v<SampleStreamCacheSourceView>);
223
233
240
247
259
271
283
288
298
301 std::uint64_t reserved_page_bytes = 0;
302 std::uint64_t source_count = 0;
303 std::uint64_t source_identity_count = 0;
304 std::uint64_t source_identity_capacity = 0;
306 std::uint64_t sources_retire_scheduled = 0;
307 std::uint64_t sources_collected = 0;
308 std::uint64_t decode_calls = 0;
309 std::uint64_t pages_published = 0;
310 std::uint64_t already_ready = 0;
311 std::uint64_t pages_retired = 0;
312 std::uint64_t retired_pages_reused = 0;
313 std::uint64_t retire_waits = 0;
315 std::uint64_t stale_requests = 0;
316 std::uint64_t no_page_available = 0;
317 std::uint64_t read_failures = 0;
318 std::uint64_t publish_failures = 0;
320};
321
327public:
330
333
335 void release() noexcept;
336 bool prepared() const noexcept;
337
342 std::uint64_t begin_audio_page_read() const noexcept;
343
347 void complete_audio_page_read(std::uint64_t epoch) noexcept;
348
353 bool update_audio_generations(std::uint64_t active_audio_generation,
354 std::uint64_t completed_audio_generation) noexcept;
355
357 FrameReader reader);
358
363 SampleStreamSourceToken token) noexcept;
364
368
370 SampleStreamSourceToken token) const noexcept;
371 bool contains_source(SampleStreamSourceToken token) const noexcept;
372 std::size_t collect_retired_sources() noexcept;
374 const SampleStreamPageDemand& demand) noexcept;
377 SampleStreamSourceToken source) noexcept;
378
381 template<std::size_t Capacity>
383 SampleStreamCommandInbox<Capacity>& inbox) noexcept {
385 while (auto command = inbox.try_pop()) {
386 ++result.commands_drained;
387 switch (command->type) {
388 case SampleStreamCommandType::DemandPage: {
389 ++result.demand_commands;
390 const auto status = request_page(command->demand);
391 if (status == SampleStreamScheduleStatus::Inserted) {
392 ++result.demands_inserted;
393 } else if (status == SampleStreamScheduleStatus::Refreshed) {
394 ++result.demands_refreshed;
395 } else if (status == SampleStreamScheduleStatus::Full) {
396 ++result.demands_rejected_full;
397 } else {
398 ++result.demands_invalid;
399 }
400 break;
401 }
402 case SampleStreamCommandType::CancelRequester:
403 ++result.cancel_requester_commands;
404 result.requests_cancelled +=
405 cancel_requester(command->requester);
406 break;
407 case SampleStreamCommandType::CancelPendingSourceDemands:
408 ++result.cancel_pending_source_commands;
409 result.requests_cancelled +=
410 cancel_pending_source_demands(command->source);
411 break;
412 }
413 }
414 return result;
415 }
416
418
420 const SampleStreamAsyncReservation& reservation) noexcept;
421
423 const SampleStreamAsyncReservation& reservation) const noexcept;
424
426 const SampleStreamAsyncReservation& reservation) noexcept;
427
429 const SampleStreamAsyncReservation& reservation,
430 BufferView<const float> decoded) noexcept;
431
435
436private:
438
439 struct SlotRecord;
440 struct SourceGenerationRecord;
441 struct Source;
442 enum class PageReservationStatus : std::uint8_t;
443 struct PageReservation;
444
445 static bool valid_source_config(
446 const SampleStreamCacheSourceConfig& config) noexcept;
447
448 static std::optional<std::uint64_t> page_storage_bytes(
449 const SampleStreamCacheSourceConfig& config) noexcept;
450
451 SampleStreamCacheSourceView make_view(Source& source) const noexcept;
452 Source* find_source_id(std::uint64_t source_id) noexcept;
453 const Source* find_source_id(std::uint64_t source_id) const noexcept;
454 Source* find_source(SampleStreamSourceToken token) noexcept;
455 const Source* find_source(SampleStreamSourceToken token) const noexcept;
456
457 static bool registration_matches(
458 const Source& source,
459 const SampleStreamAsyncReservation& reservation) noexcept;
460
461 static bool matching_filling_slot(
462 const Source& source,
463 const SampleStreamAsyncReservation& reservation) noexcept;
464
465 static bool has_matching_filling_page(
466 const Source& source,
467 const SampleStreamPageRequest& request) noexcept;
468
469 Source* matching_async_source(
470 const SampleStreamAsyncReservation& reservation) noexcept;
471
472 static std::optional<SampleStreamPageRequest> canonical_request(
473 const Source& source,
474 const SampleStreamPageDemand& demand) noexcept;
475
476 PageReservation reserve_page(Source& source,
477 std::uint64_t reservation_serial) noexcept;
478
479 std::uint64_t take_reservation_serial() noexcept;
480
481 static bool cancel_fill(Source& source,
482 std::uint32_t page_index,
483 std::uint64_t reservation_serial) noexcept;
484
485 static bool finish_async_reservation(Source& source) noexcept;
486
487 std::vector<std::unique_ptr<Source>> sources_;
488 std::vector<SourceGenerationRecord> source_generations_;
489 SampleStreamScheduler scheduler_;
490 SampleMemoryGovernor internal_memory_governor_;
491 SampleMemoryGovernorHandle memory_governor_;
492 std::uint64_t active_audio_generation_ = 0;
493 std::uint64_t completed_audio_generation_ = 0;
494 // Written in opposite directions by the service and audio threads. Keep
495 // each endpoint on its own cache line so the per-block load does not share
496 // ownership with the infrequent retirement/completion store.
497 alignas(64) std::atomic<std::uint64_t> published_page_retirement_epoch_{0};
498 alignas(64) std::atomic<std::uint64_t> completed_page_retirement_epoch_{0};
499 std::uint64_t next_page_retirement_epoch_ = 1;
500 std::uint64_t next_registration_epoch_ = 1;
501 std::uint64_t next_reservation_serial_ = 1;
502 std::size_t source_identity_capacity_ = 0;
503 std::uint32_t maximum_async_reservations_per_source_ = 1;
504 bool prepared_ = false;
505 SampleStreamCacheServiceStats stats_{};
506};
507
508} // namespace pulp::audio
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
Definition sample_memory_governor.hpp:16
Copyable lifetime-safe reservation/stats endpoint.
Definition sample_memory_governor.hpp:165
Shared off-audio-thread admission governor for resident preload heads and stream-cache pages.
Definition sample_memory_governor.hpp:280
Bounded shared-page cache with deterministic caller-driven servicing.
Definition sample_stream_service.hpp:326
bool discard_unpublished_source(SampleStreamSourceToken token) noexcept
Remove a source that never became reachable from an audio-thread asset.
SampleStreamServiceStatus service_once() noexcept
std::size_t cancel_requester(SampleStreamRequesterToken requester) noexcept
SampleStreamCacheService & operator=(const SampleStreamCacheService &)=delete
SampleStreamCacheService(const SampleStreamCacheService &)=delete
std::size_t collect_retired_sources() noexcept
SampleStreamSourceRetireStatus retire_source_after_asset_unpublish(SampleStreamSourceToken token) noexcept
Call only after the asset publisher has stopped issuing this source view.
SampleStreamSchedulerStats scheduler_stats() const noexcept
SampleStreamCacheServiceStats stats() const noexcept
bool commit_async_dispatch(const SampleStreamAsyncReservation &reservation) noexcept
SampleStreamAsyncCompletionStatus publish_async_reservation(const SampleStreamAsyncReservation &reservation, BufferView< const float > decoded) noexcept
bool update_audio_generations(std::uint64_t active_audio_generation, std::uint64_t completed_audio_generation) noexcept
Updates the generation currently allowed to hold page views and the last generation whose audio callb...
bool contains_source(SampleStreamSourceToken token) const noexcept
void complete_audio_page_read(std::uint64_t epoch) noexcept
RT-safe page-lifetime barrier completion.
SampleStreamAsyncCompletionStatus cancel_async_reservation(const SampleStreamAsyncReservation &reservation) noexcept
std::size_t cancel_pending_source_demands(SampleStreamSourceToken source) noexcept
SampleStreamCommandDrainResult drain_commands(SampleStreamCommandInbox< Capacity > &inbox) noexcept
Applies all currently queued commands in producer order.
Definition sample_stream_service.hpp:382
bool prepare(const SampleStreamCacheServiceConfig &config)
SampleStreamAsyncReserveResult reserve_async_page() noexcept
SampleStreamScheduleStatus request_page(const SampleStreamPageDemand &demand) noexcept
std::uint64_t begin_audio_page_read() const noexcept
RT-safe page-lifetime barrier entry.
bool async_reservation_has_interest(const SampleStreamAsyncReservation &reservation) const noexcept
bool retirement_watermark_reached(SampleStreamSourceToken token) const noexcept
SampleStreamSourceAddResult add_source(const SampleStreamCacheSourceConfig &config, FrameReader reader)
friend struct SampleStreamCacheServiceTestAccess
Definition sample_stream_service.hpp:437
Prepared bounded command port from one RT producer to the service owner.
Definition sample_stream_service.hpp:91
friend class SampleStreamCacheService
Definition sample_stream_service.hpp:129
SampleStreamCommandPushStatus demand_page(const SampleStreamPageDemand &demand) noexcept
Definition sample_stream_service.hpp:93
SampleStreamCommandPushStatus cancel_pending_source_demands(SampleStreamSourceToken source) noexcept
Definition sample_stream_service.hpp:109
static constexpr std::size_t capacity() noexcept
Definition sample_stream_service.hpp:126
SampleStreamCommandPushStatus cancel_requester(SampleStreamRequesterToken requester) noexcept
Definition sample_stream_service.hpp:101
SampleStreamCommandInboxTelemetry telemetry() const noexcept
Definition sample_stream_service.hpp:117
Single-owner background scheduler for shared sample-cache page fills.
Definition sample_stream_scheduler.hpp:79
Definition sample_stream_service.hpp:158
friend class SampleStreamCacheService
Definition sample_stream_service.hpp:175
bool matches(SampleStreamSourceToken token, const SampleStreamWindow *window, std::uint64_t total_frames, std::uint64_t page_frames, std::uint64_t registration_epoch) const noexcept
Definition sample_stream_service.hpp:162
Definition sample_stream_window.hpp:78
Definition spsc_queue.hpp:23
Definition analyzer_provider.hpp:12
@ Reserved
Definition sample_slot_bank.hpp:15
@ Published
Definition sample_slot_bank.hpp:18
@ DuplicateSource
Definition sample_stream_decode_pool.hpp:96
@ Added
Definition sample_stream_decode_pool.hpp:94
SampleStreamDemandClass
Definition sample_stream_scheduler.hpp:15
@ Sustain
Definition sample_stream_scheduler.hpp:17
@ SourceInFlight
Definition sample_stream_decode_pool.hpp:117
std::function< std::uint64_t(std::uint64_t start_frame, BufferView< float > dest, std::uint64_t frames)> FrameReader
Caller-supplied random-access frame reader.
Definition streaming_sample_source.hpp:73
@ AllocationFailed
Definition finite_time_stretch.hpp:27
SampleStreamScheduleStatus
Definition sample_stream_scheduler.hpp:35
@ Full
Definition sample_stream_scheduler.hpp:38
@ StaleGeneration
Definition sample_stream_decode_pool.hpp:67
@ StaleReservation
Definition sample_stream_decode_pool.hpp:68
@ StaleSource
Definition sample_stream_decode_pool.hpp:66
@ Idle
Definition instrument_envelope.hpp:9
SampleStreamAsyncCompletionStatus
Definition sample_stream_service.hpp:289
@ StaleRegistration
Definition sample_stream_service.hpp:293
SampleStreamCommandPushStatus
Definition sample_stream_service.hpp:76
@ Full
Definition sample_stream_service.hpp:78
@ Enqueued
Definition sample_stream_service.hpp:77
SampleStreamCommandType
Definition sample_stream_service.hpp:61
@ CancelRequester
Definition sample_stream_service.hpp:63
@ DemandPage
Definition sample_stream_service.hpp:62
@ CancelPendingSourceDemands
Definition sample_stream_service.hpp:64
SampleStreamSourceAddStatus
Definition sample_stream_service.hpp:224
@ SourceIdentityCapacityExceeded
Definition sample_stream_service.hpp:229
@ InvalidConfig
Definition sample_stream_service.hpp:226
@ Added
Definition sample_stream_service.hpp:225
@ CopyFailed
Definition sample_stream_async_service.hpp:57
@ Canceled
Definition sample_stream_decode_pool.hpp:44
@ BudgetExceeded
Definition sample_memory_governor.hpp:150
SampleStreamSourceRetireStatus
Definition sample_stream_service.hpp:234
@ Scheduled
Definition sample_stream_service.hpp:235
@ InvalidGeneration
Definition sample_stream_service.hpp:236
@ AlreadyScheduled
Definition sample_stream_service.hpp:238
SampleStreamAsyncReserveStatus
Definition sample_stream_service.hpp:260
@ SerialExhausted
Definition sample_stream_service.hpp:269
@ Idle
Definition sample_stream_service.hpp:262
SampleStreamServiceStatus
Definition sample_stream_service.hpp:248
@ AlreadyReady
Definition sample_stream_service.hpp:251
@ NoPageAvailable
Definition sample_stream_service.hpp:255
@ WaitingForAudioGeneration
Definition sample_stream_service.hpp:253
@ PageRetired
Definition sample_stream_service.hpp:252
@ PublishFailed
Definition sample_stream_service.hpp:257
@ ReadFailed
Definition sample_stream_service.hpp:256
STL namespace.
Real-time-safe streaming sample playback primitive.
Definition sample_memory_governor.hpp:40
Definition sample_stream_service.hpp:272
bool final_page
Definition sample_stream_service.hpp:280
std::uint64_t reservation_serial
Definition sample_stream_service.hpp:276
SampleStreamPageRequest request
Definition sample_stream_service.hpp:281
std::uint32_t page_index
Definition sample_stream_service.hpp:279
std::uint64_t frame_count
Definition sample_stream_service.hpp:278
std::uint64_t registration_epoch
Definition sample_stream_service.hpp:275
SampleStreamSourceRegistrationProof registration
Definition sample_stream_service.hpp:274
std::uint64_t start_frame
Definition sample_stream_service.hpp:277
SampleStreamSourceToken source
Definition sample_stream_service.hpp:273
Definition sample_stream_service.hpp:284
SampleStreamAsyncReservation reservation
Definition sample_stream_service.hpp:286
SampleStreamAsyncReserveStatus status
Definition sample_stream_service.hpp:285
Definition sample_stream_service.hpp:28
SampleMemoryGovernorHandle memory_governor
Optional shared preload+page issuer.
Definition sample_stream_service.hpp:41
std::uint64_t page_memory_budget_bytes
Page-only cap used when memory_governor is empty.
Definition sample_stream_service.hpp:38
std::uint32_t maximum_async_reservations_per_source
Maximum number of independently leased Filling pages for one source.
Definition sample_stream_service.hpp:35
std::size_t scheduler_capacity
Definition sample_stream_service.hpp:29
std::size_t source_identity_capacity
Maximum number of distinct source IDs whose highest generation is retained for ABA rejection.
Definition sample_stream_service.hpp:33
Definition sample_stream_service.hpp:299
std::uint64_t sources_collected
Definition sample_stream_service.hpp:307
std::uint64_t retired_pages_reused
Definition sample_stream_service.hpp:312
std::uint64_t source_identity_count
Definition sample_stream_service.hpp:303
std::uint64_t publish_failures
Definition sample_stream_service.hpp:318
std::uint64_t no_page_available
Definition sample_stream_service.hpp:316
std::uint64_t sources_retire_scheduled
Definition sample_stream_service.hpp:306
std::uint64_t source_identity_capacity
Definition sample_stream_service.hpp:304
std::uint64_t reserved_page_bytes
Definition sample_stream_service.hpp:301
std::uint64_t read_failures
Definition sample_stream_service.hpp:317
std::uint64_t decode_calls
Definition sample_stream_service.hpp:308
std::uint64_t stale_requests
Definition sample_stream_service.hpp:315
std::uint64_t pages_published
Definition sample_stream_service.hpp:309
std::uint64_t already_ready
Definition sample_stream_service.hpp:310
std::uint64_t async_reservations_high_water
Definition sample_stream_service.hpp:319
std::uint64_t pages_retired
Definition sample_stream_service.hpp:311
std::uint64_t source_identity_capacity_rejections
Definition sample_stream_service.hpp:305
std::uint64_t source_count
Definition sample_stream_service.hpp:302
SampleMemoryGovernorStats memory
Definition sample_stream_service.hpp:300
std::uint64_t retire_waits
Definition sample_stream_service.hpp:313
std::uint64_t invalid_audio_generation_updates
Definition sample_stream_service.hpp:314
Definition sample_stream_service.hpp:44
std::uint32_t cache_page_count
Definition sample_stream_service.hpp:49
SampleStreamSourceToken token
Definition sample_stream_service.hpp:45
std::uint64_t page_frames
Definition sample_stream_service.hpp:48
std::uint64_t total_frames
Definition sample_stream_service.hpp:47
std::uint32_t channels
Definition sample_stream_service.hpp:46
Definition sample_stream_service.hpp:200
SampleStreamWindow * window
Definition sample_stream_service.hpp:202
std::uint64_t page_frames
Definition sample_stream_service.hpp:204
SampleStreamSourceRegistrationProof registration
Definition sample_stream_service.hpp:206
std::uint64_t registration_epoch
Definition sample_stream_service.hpp:205
SampleStreamSourceToken token
Definition sample_stream_service.hpp:201
bool valid() const noexcept
Definition sample_stream_service.hpp:209
SampleMemoryGovernorEpoch memory_governor_epoch
Definition sample_stream_service.hpp:207
std::uint64_t total_frames
Definition sample_stream_service.hpp:203
Definition sample_stream_service.hpp:143
std::size_t demands_rejected_full
Definition sample_stream_service.hpp:150
std::size_t demands_refreshed
Definition sample_stream_service.hpp:149
std::size_t commands_drained
Definition sample_stream_service.hpp:144
std::size_t cancel_requester_commands
Definition sample_stream_service.hpp:146
std::size_t cancel_pending_source_commands
Definition sample_stream_service.hpp:147
std::size_t demand_commands
Definition sample_stream_service.hpp:145
std::size_t requests_cancelled
Definition sample_stream_service.hpp:152
std::size_t demands_invalid
Definition sample_stream_service.hpp:151
std::size_t demands_inserted
Definition sample_stream_service.hpp:148
Definition sample_stream_service.hpp:81
std::uint64_t overflow_count
Definition sample_stream_service.hpp:84
std::size_t pending
Definition sample_stream_service.hpp:82
std::size_t capacity
Definition sample_stream_service.hpp:83
Definition sample_stream_service.hpp:67
SampleStreamSourceToken source
Definition sample_stream_service.hpp:71
SampleStreamRequesterToken requester
Definition sample_stream_service.hpp:70
SampleStreamCommandType type
Definition sample_stream_service.hpp:68
SampleStreamPageDemand demand
Definition sample_stream_service.hpp:69
Definition sample_stream_service.hpp:52
std::uint64_t resident_source_frames
Definition sample_stream_service.hpp:56
SampleStreamSourceToken source
Definition sample_stream_service.hpp:53
SampleStreamRequesterToken requester
Definition sample_stream_service.hpp:54
std::uint64_t page_index
Definition sample_stream_service.hpp:55
SampleStreamDemandClass demand_class
Definition sample_stream_service.hpp:58
double consumption_frames_per_second
Definition sample_stream_service.hpp:57
Definition sample_stream_scheduler.hpp:21
Definition sample_stream_service.hpp:23
std::uint64_t requester_generation
Definition sample_stream_service.hpp:25
std::uint64_t requester_id
Definition sample_stream_service.hpp:24
Definition sample_stream_scheduler.hpp:42
Definition sample_stream_service.hpp:241
SampleStreamCacheSourceView view
Definition sample_stream_service.hpp:243
bool added() const noexcept
Definition sample_stream_service.hpp:245
SampleStreamSourceAddStatus status
Definition sample_stream_service.hpp:242
Definition sample_stream_service.hpp:18
std::uint64_t source_generation
Definition sample_stream_service.hpp:20
std::uint64_t source_id
Definition sample_stream_service.hpp:19