# AsyncProcedureCall in maplibre::io::apc - Rust
APCs define an interface for performing work asynchronously. This work can be implemented through procedures which can be called asynchronously, hence the name AsyncProcedureCall or APC for short.

# Trait maplibre::io::apc::AsyncProcedureCall

source ·

    pub trait AsyncProcedureCall<K: OffscreenKernelEnvironment>: 'static {
        type Context: Context + Send + Clone;
        type ReceiveIterator<F: FnMut(&Message) -> bool>: Iterator<Item = Message>;

        // Required methods
        fn receive<F: FnMut(&Message) -> bool>(
            &self,
            filter: F
        ) -> Self::ReceiveIterator<F>;
        fn call(
            &self,
            input: Input,
            procedure: AsyncProcedure<K, Self::Context>
        ) -> Result<(), CallError>;
    }

Expand description

APCs define an interface for performing work asynchronously. This work can be implemented through procedures which can be called asynchronously, hence the name AsyncProcedureCall or APC for short.

APCs serve as an abstraction for doing work on a separate thread, and then getting responses back. An asynchronous procedure call can for example be performed by using message passing. In fact this could theoretically work over a network socket.

It is possible to schedule work on a remote host by calling `AsyncProcedureCall::call()` and getting the results back by calling the non-blocking function `AsyncProcedureCall::receive()`. The `AsyncProcedureCall::receive()` function returns a struct which implements [`Transferables`].

### Transferables

Based on whether the current platform supports shared-memory or not, the implementation of APCs might want to send the whole data from the worker to the caller back or just pointers to that data. The [`Transferables`] trait allows developers to define that and use different data layouts for different platforms.

### Message Passing vs APC

One might wonder why this is called `AsyncProcedureCall` instead of `MessagePassingInterface`. The reason for this is quite simple. We are actually referencing and calling procedures which are defined in different threads, processes or hosts. That means, that an `AsyncProcedureCall` is actually distinct from a `MessagePassingInterface`.

### Current Implementations

We currently have two implementation for APCs. One uses the Tokio async runtime on native targets in `SchedulerAsyncProcedureCall`. For the web we implemented an alternative way to call APCs which is called [`PassingAsyncProcedureCall`]. This implementation does not depend on shared-memory compared to `SchedulerAsyncProcedureCall`. In fact, on the web we are currently not depending on shared-memory because that feature is hidden behind feature flags in browsers (see here).

## Required Associated Types§

source

#### type Context: Context + Send + Clone

source

#### type ReceiveIterator<F: FnMut(&Message) -> bool>: Iterator<Item = Message>

## Required Methods§

source

#### fn receive<F: FnMut(&Message) -> bool>( &self, filter: F ) -> Self::ReceiveIterator<F>

Try to receive a message non-blocking.

source

#### fn call( &self, input: Input, procedure: AsyncProcedure<K, Self::Context> ) -> Result<(), CallError>

Call an `AsyncProcedure` using some `Input`. This function is non-blocking and returns immediately.

## Object Safety§

This trait is not object safe.

## Implementors§

source §

### impl<K: OffscreenKernelEnvironment, S: Scheduler> AsyncProcedureCall<K> for SchedulerAsyncProcedureCall<K, S>

§

#### type Context = SchedulerContext

§

#### type ReceiveIterator<F: FnMut(&Message) -> bool> = IntoIter<Message>