PrismCore / API reference / Probing and input
Protocol
CancellablePrismCoreInput
protocol CancellablePrismCoreInput : PrismCoreInputDeclared in Sources/PrismCore/Probe/PrismCoreInput.swift · PrismCore 3.5.4
A PrismCoreInput whose in-flight read or seek can be released from another thread.
The plain protocol has no way out of a blocked call. ReadInterruptGuard bounds blocking operations with FFmpeg's interrupt_callback, which FFmpeg polls between reads — so it reaches libavformat's own I/O and stops dead at the edge of a host's synchronous read(into:). An SMB share whose server went away, or a debrid link that stopped feeding, therefore parks the calling thread for as long as the host's own transport takes to give up: minutes, or never. That thread is the probe's, or the producer's — and a parked producer is what used to make PrismCoreSession.stop() hang, which in a host app is a frozen UI.
Conforming is what gives the engine a way in.
The contract, both halves. The engine promises to call cancelInFlightOperation() whenever the read guard on this input's context becomes interrupted — an expired probe/index-load budget, or an explicit cancellation such as stop(). The host promises that the read or seek blocked at that moment then returns, promptly, in one of two ways the engine accepts equally:
- throwing — the usual shape, and the one that carries a reason. What is thrown is recorded as
PrismCoreInputError.readFailed/.seekFailed, but on an interrupted context it is the abort, not the error, that decides the outcome, so a plain "cancelled" error is fine; - a short count,
0included. Zero normally means end of stream —read(into:)says so — but a read released by a cancellation is read back as the abort it is and never as EOF, because the engine knows it asked. A short positive count is simply the bytes that did arrive.
Both are honoured only while the guard is interrupted. A host that returns 0 at any other moment is still declaring EOF.
Two requirements on the implementation:
- it may be called concurrently with
readorseek— that is the whole point — so it must not take a lock those hold, and must not touch state they mutate without its own synchronization. Waking a socket, cancelling aURLSessionTask, setting an atomic flag: all fine; - it may be called when nothing is in flight, and must then do nothing. The engine cannot see inside the host, so it never guesses; a deadline that expires between two reads calls this against an idle input.
An input that does not conform keeps working exactly as before. The engine checks for this conformance once, when it installs the input, and leaves a notice in the unified log when it is absent — so a thread wedged an hour later has a breadcrumb instead of being a mystery.
Instance methods
func cancelInFlightOperation()Release whatever read or seek is blocked right now, if any.
Called from a thread that is not the one inside read/seek, and possibly when neither is running — in which case it must be a no-op. It must return promptly: the engine calls it from a deadline timer and from stop(), neither of which can afford to block.
Generated from the public symbols of PrismCore 3.5.4. All types