# Arenas

> UForm for C

Callers lend memory, never a way to allocate it, and every byte has one owner that picks where it lives once:

- Weights and their packed copies belong to the model, placed by its load's residency.
- Weights, gradients and optimizer moments under training belong to the trainer, on its executor's devices.
- Activations, scratch and staging belong to the executor, grown to a high-water mark.

Every output whose length scales with the call lands in an arena, while fixed-size reports such as stats and descriptions stay caller fields.
`uform_arena_init` places an arena where its executor computes, host pages or the memory of its GPU, and allocates nothing until a call writes into it.
A call rewinds the arena it is given, invalidating the previous call's outputs, and grows it only when the new outputs outsize everything it held, so a steady loop allocates once.

- A `NULL` arena, or inputs inside the arena the call rewinds, report `uform_status_invalid_argument_k`.
- An arena serves one call at a time, and a second call naming it finishes `uform_status_contended_k`.
- A call on another residency or device than the arena's reports `uform_status_device_k`.
- A GPU arena grows on the first stream of the executor that made it, so it serves only that executor and is freed before it.

```c
uform_arena_t arena = NULL;
uform_arena_init(&(uform_arena_init_t){.arena = &arena, .executor = executor, .outcome = &outcome});
for (size_t batch = 0; batch != batches_count; ++batch) {
    encode.texts = texts[batch], encode.arena = arena, encode.embeddings = &embeddings;
    uform_text_encode(&encode);
    if (encode.outcome->status != uform_status_success_k) break;
    consume(embeddings, encode.count); // valid until the next call given `arena`
}
uform_arena_free(arena);
```

### Rows and Tapes

A verb's `count` is its batch axis and nothing else.
Outputs are views the call writes packed into its arena, so none carries a capacity for the caller to pick.
`uform_rows_view_t` holds one row per item as `data`, `stride`, `columns` and `scalar`, field for field USearch's rows, so pooled embeddings feed an index as they are.
Ragged inputs are `uform_tape_view_t` tapes laid out as Apache Arrow lays them: elements end to end in `data`, and `count + 1` offsets in host memory around them.
Ragged outputs, such as per-token states, are `uform_rows_tape_view_t`: packed rows and one more offset than items.
On a VRAM executor every output is device memory, which the caller copies out itself or hands to a USearch VRAM index as it is.

`#include <uform/types.h>`

## uform_arena_t

Memory the library allocates for the outputs only a call can size, reused across calls.

```c
typedef struct uform_arena_handle_t * uform_arena_t;
```

Memory

Made by [`uform_arena_init`](#uform_arena_init) where its executor computes: host pages on its memory domains, or the memory of its GPU, and a GPU that runs out reports [`uform_status_out_of_memory_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_out_of_memory_k) rather than falling back to the host. Each call given the arena rewinds it, which invalidates every output of the previous call, and refills it, growing only when the new outputs outsize everything it held, so a steady loop allocates once. To keep one call's outputs alive past the next call, pass the next call another arena.

- A `NULL` arena is refused with [`uform_status_invalid_argument_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_invalid_argument_k).
- A call whose inputs point into the arena it is about to rewind reports [`uform_status_invalid_argument_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_invalid_argument_k).
- An arena serves one call at a time; a second call naming it finishes [`uform_status_contended_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_contended_k), and a deferred one does so at submission.
- A call on another residency or device than the arena's, or a call naming a GPU arena with another executor than the one that made it, `NULL` included, reports [`uform_status_device_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_device_k).
- A blocking call borrows the arena until it returns, and a deferred one holds it until final.
- A call that fails or is cancelled leaves its outputs `NULL`.

Notes: A GPU arena grows, fills and frees on the first stream of the executor that made it, so it serves only calls on that executor, and must be freed before that executor is.

## uform_arena_description_t

Where an arena's outputs live.

```c
struct uform_arena_description_t
```

- `residency` `uform_residency_t`: RAM for host pages, VRAM for one device's memory.
- `device` `int32_t`: The UForm ordinal of the device, as [`uform_gpu_devices`](https://www.unum.cloud/docs/uform/c/executors.md#uform_gpu_devices) lists it, or -1 for host pages.

## uform_arena_init

Creates an empty arena where `executor` computes, so its placement is decided once and GPU code keeps its outputs on the device without asking.

```c
void uform_arena_init(uform_arena_init_t *arguments);
```

Nothing is allocated until a call writes into it. An arena of host pages may outlive the executor that made it, keeping its own memory until it is freed; a GPU arena keeps the rule [uform_arena_t](#uform_arena_t) notes.

- `arena`: Output for the new arena.
- `executor`: The executor whose calls the arena serves, which decides where it lives; `NULL` serves calls on the calling thread from host pages.
- `outcome`: Output for the outcome, final once its status leaves [`uform_status_deferred_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_deferred_k).

## uform_arena_free

Frees the arena and every output in it; `NULL` is safe, and it cannot fail, so takes no outcome.

```c
void uform_arena_free(uform_arena_t arena);
```

Waits until every deferred call naming the handle is final.

- `arena` (inout): The arena to be freed; invalid afterwards.

## uform_arena_describe

Reports where an arena's outputs live, as the executor that made it decided, so a caller reads them as host memory or hands them to device code without remembering that executor.

```c
void uform_arena_describe(uform_arena_describe_t *arguments);
```

- `arena`: The arena to describe.
- `outcome`: Output for the outcome, final once its status leaves [`uform_status_deferred_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_deferred_k).
- `description`: Output for where the arena's outputs live.

Statuses: - [`uform_status_invalid_argument_k`](https://www.unum.cloud/docs/uform/c/errors.md#uform_status_invalid_argument_k) A `NULL` arena or description.

