JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Commit some funky docs

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨c4cba92

⁨docs/ABI.md⁩ - ⁨4502⁩ bytes
Raw

ABI

Value ABI

At its core, the Giterated Runtime uses the extern "C" ABI. What that means is likely platform specific, and doesn’t matter. You are intended to compile the Giterated Runtime and Plugins for your local machine, all with a similar idea of what your “local machine” is.

Values are passed using the FFI type. There are four categories of value that the FFI type enables you to pass:

FFI Type CategoryPlaced Backing?Owned?
SliceHeap/StackNo
Referenced SliceStackNo
Referenced ValueNoNo
Owned ValueHeapYes

For an FFI type to have a “placed backing” is for it to have some data structure beyond the data it represents, placed somewhere in memory. Some types only require stack placement while some offer both stack and heap placement.

Stack-placed values can be shared by PinnedRef and PinnedMut, and thus can only be owned by the caller.

Heap-placed values can be shared by Owned, PinnedRef, and PinnedMut. They can be owned by any one consumer, When the handle with ownership is Drop’d by the sole consumer, it will free the object using the associated Drop callback.

Safety Intents

This API is designed to simplify interaction with FFI values, and provide a static ABI for those values to be passed. It is key to enabling ownership across FFI while ensuring associated dropping and allocation freeing logic is ran.

The contract the developer has to follow is made simpler by this system, and it allows for generic code to be written to interact with FFI-given values and pass values using FFI.

Stability Guarantees

There are no plans to guarantee stability until 1.0.0. At that point you can expect the ABI to remain stable until the major version is incremented again. There will be an appropriate deprecation process and changeover period.

Memory Representation

Please check out the source code, sorry if you needed that from the docs!

Object, Operation, Setting, Value, Plugin, and Runtime ABIs

The Giterated Runtime uses vtables to accomplish the goal of ensuring maximum compatibility. For every object that is shared between plugins, a vtable is used to allow each plugin to provide their own code for interacting with the object.

When objects switch “runtime domains” (e.g. host -> plugin, plugin -> plugin, plugin -> host), their vtable is swapped out for the new runtime domain’s own vtables.

Untyped “Objects” (see above header for list)

Untyped objects, in memory, are represented by a data pointer and a vtable pointer. Exactly like Rust traits. However, to prevent small compilation differences and other random garbage from making the interface not perfectly compatible we use the local plugin’s idea of the vtable for the object at all times. An object that the plugin does not have a vtable for cannot be relevant to the plugin.

It is important that the object’s base representation in memory remain unchanged between major versions, but the vtables that provide methods for that object may be grown. The methods that operate on that object may be changed in an non-breaking fashion, and bugs can be fixed.

Futures ABI

The Giterated Runtime has an async runtime that allows for futures to be shared and awaited across FFI boundaries while only executing the future within the context of the Plugin who is running the underlying future.

Futures are spawned onto the RuntimeState with the RuntimeFuturesExt trait. This takes a Rust future, boxes it, and provides a RuntimeFuture handle that can be used to drive the underlying Rust future locally. The RuntimeFuture handle is thread-safe and can be shared with the callee and .await’d directly like any other future.

RuntimeFuture

The RuntimeFuture mixes a vtable with data to allow for any caller to drive a spawned future. It contains:

When the RuntimeFuture is polled, it causes the inner future to also be polled. We provide the inner future with a waker that triggers the RuntimeFuture’s waker so it is polled again. Breaking character to point out how freaking cool that is.

RuntimeFutures drop the associated inner future as they drop.