Skip to main content

SyncCompletion

Struct SyncCompletion 

Source
pub struct SyncCompletion<T> { /* private fields */ }
Expand description

A synchronous completion handler for async FFI callbacks

This type provides a way to block until an async callback completes and retrieve the result. It uses Arc<...> internally for thread-safe signaling between the callback and the waiting thread, with an AtomicBool guard that defends against Swift firing the completion callback more than once (which would otherwise be use-after-free in Arc::from_raw).

Implementations§

Source§

impl<T> SyncCompletion<T>

Source

pub fn new() -> (Self, SyncCompletionPtr)

Create a new completion handler and return the context pointer for FFI

Returns a tuple of (completion, context_ptr) where:

  • completion is used to wait for and retrieve the result
  • context_ptr should be passed to the FFI callback
Source

pub fn wait(self) -> Result<T, String>

Wait for the completion callback and return the result

This method blocks until the callback signals completion.

§Errors

Returns an error string if the callback signaled an error.

§Panics

Panics if the internal mutex is poisoned.

Source

pub unsafe fn complete_ok(context: SyncCompletionPtr, value: T)

Signal successful completion with a value

§Safety

The context pointer must be a valid pointer obtained from SyncCompletion::new(). This function consumes the Arc reference, so it must only be called once per context.

Source

pub unsafe fn complete_err(context: SyncCompletionPtr, error: String)

Signal completion with an error

§Safety

The context pointer must be a valid pointer obtained from SyncCompletion::new(). This function consumes the Arc reference, so it must only be called once per context.

Source

pub unsafe fn complete_with_result( context: SyncCompletionPtr, result: Result<T, String>, )

Signal completion with a result

§Safety

The context pointer must be a valid pointer obtained from SyncCompletion::new() and not yet freed. The intended FFI contract is that the callback fires exactly once per context.

The consumed AtomicBool provides defence in depth against Swift firing the callback twice on the same still-live context: the second invocation atomically observes consumed == true and returns without touching the Arc, preventing the double-Arc::from_raw that would otherwise corrupt the refcount.

Limitation: this guard does not protect against the pathological case where (a) the legitimate callback completed fully, (b) the corresponding SyncCompletion was dropped (so the inner allocation was freed), and (c) Swift then fires the callback a third time with the same now-dangling pointer. The initial &*context.cast::<...>() deref in that case is use-after-free. Defending against that scenario would require either a process-wide allocator (so freed pointers are never reused) or an indirection through a registry — both beyond the scope of this guard. Fortunately Apple’s ScreenCaptureKit callbacks do not exhibit this pattern in practice; this # Safety note documents the residual contract for future maintainers.

§Panics

Panics if the internal mutex is poisoned.

Source§

impl SyncCompletion<()>

Source

pub extern "C" fn callback( context: *mut c_void, success: bool, msg: *const i8, )

C callback for operations that return (context, success, error_msg)

This can be used directly as an FFI callback function.

Trait Implementations§

Source§

impl<T> Default for SyncCompletion<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> Freeze for SyncCompletion<T>

§

impl<T> RefUnwindSafe for SyncCompletion<T>

§

impl<T> Send for SyncCompletion<T>
where T: Send,

§

impl<T> Sync for SyncCompletion<T>
where T: Send,

§

impl<T> Unpin for SyncCompletion<T>

§

impl<T> UnsafeUnpin for SyncCompletion<T>

§

impl<T> UnwindSafe for SyncCompletion<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.