VideoInterop.Lease (video_interop v0.1.0)

Copy Markdown View Source

Per-consumer producer lifetime token for a borrowed video interop frame.

A lease holder is unique. Before fan-out, a splitter must synchronously call retain/2 for every additional branch and give each branch a different returned lease. The producer registers the new holder as pending before acknowledging the retain request. The caller then confirms receipt. It must process retain/confirm/cancel messages in mailbox order; a timeout sends {:video_interop_cancel_retain, token, child_holder} to remove a possibly late registration. Releases are idempotent per {token, holder} pair.

Producers should issue managed leases through VideoInterop.LeaseOwner, whose isolated mailbox prevents media traffic in the producing element from delaying retirement. new/2 is a low-level unmanaged constructor for implementations that provide equivalent registration, isolation, idempotency, and draining themselves.

The opaque backend token should provide an owner-crash destructor fallback. A producer may also attach a unique VideoInterop.AbandonmentGuard authority envelope to each holder. Its verified native resource destructor is an eventual fallback for a holder-bearing BEAM term that disappears without an explicit release. Normal release remains the primary path.

Summary

Functions

Creates an unmanaged root lease.

Synchronously obtains a unique child holder for an additional consumer.

Types

t()

@type t() :: %VideoInterop.Lease{
  abandonment_guard: VideoInterop.AbandonmentGuard.t() | nil,
  holder: reference(),
  owner: pid(),
  token: term()
}

Functions

cancel_retain_tag()

@spec cancel_retain_tag() :: :video_interop_cancel_retain

confirm_retain_tag()

@spec confirm_retain_tag() :: :video_interop_confirm_retain

new(owner, token)

@spec new(pid(), term()) :: t()

Creates an unmanaged root lease.

Prefer VideoInterop.LeaseOwner.issue/3. This constructor does not register the holder or provide mailbox isolation, fan-out accounting, release callbacks, or shutdown draining.

release(lease)

@spec release(t()) :: :ok

release_tag()

@spec release_tag() :: :video_interop_release

retain(lease, timeout \\ 5000)

@spec retain(t(), timeout()) ::
  {:ok, t()} | {:error, :timeout | {:owner_down, term()} | term()}

Synchronously obtains a unique child holder for an additional consumer.

The owner receives:

{:video_interop_retain, token, parent_holder, child_holder, reply_to, request_ref}

request_ref is a process alias. The owner must register child_holder as pending, monitor reply_to, construct a fresh child guard, and send {:video_interop_retained, request_ref, {:ok, child_guard}} to the alias. Receipt is committed by {:video_interop_confirm_retain, token, child_holder, request_ref}; caller death or cancellation before that confirmation must remove the pending holder. The child lease replaces both the holder and guard; it never copies the parent's guard.

retain_tag()

@spec retain_tag() :: :video_interop_retain

retained_tag()

@spec retained_tag() :: :video_interop_retained