# `Hyperlang.Limits`
[🔗](https://github.com/hyperbob-labs/hyperlang/blob/v0.1.0/lib/hyperlang/limits.ex#L1)

Process-group limits for confined code.

A group owns a reduction rate, a total reduction ceiling, and any processes
attached to it. A single watchdog samples every live member, suspends a
group after its period quota is spent, resumes it at rollover, and
terminates members that cross a ceiling. Each member's wall deadline is a
dedicated timer.

`Hyperlang.run/4` manages its own groups. Syscall hosts use this module to
meter processes they spawn for a guest: create a group with `group/1`,
`attach/3` the process, and `delete/1` the group when its owner is done.
The process that calls `group/1` owns the group; its exit deletes it.

Limit keys are `rate` (`%{quota: reductions, period_ms: ms}`), `ceiling`
(total reductions), `wall_ms`, `heap_words` and `max_procs` (guest-spawned
children; `0` admits none). `:infinity` or `nil` means unbounded.

# `group`

```elixir
@type group() :: %Hyperlang.Limits.Group{id: term(), limits: term()}
```

# `attach`

```elixir
@spec attach(group(), pid(), map() | keyword()) :: :ok | {:error, :eagain}
```

Attach `pid` to `group` with per-member limits (`wall_ms`, `heap_words`,
`ceiling`).

Returns `{:error, :eagain}` when the group's `max_procs` is exhausted.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `delete`

```elixir
@spec delete(group()) :: :ok
```

Destroy a group and kill its remaining guest processes. Idempotent.

# `detach`

```elixir
@spec detach(group(), pid()) :: :ok
```

Stop metering `pid` and release its member slot.

# `detach_children`

```elixir
@spec detach_children(group()) :: :ok
```

Terminate every guest-spawned member of `group`, freeing its spawn slots.
A child cannot survive the lifetime of the run that owns its accounting.

# `group`

```elixir
@spec group(map() | keyword()) :: group()
```

Create a group with `limits`, owned by the calling process.

# `limit`

```elixir
@spec limit(group(), map() | keyword()) :: :ok | {:error, :closed}
```

Replace the limits of a live group. Returns `{:error, :closed}` for a deleted group.

# `stat`

```elixir
@spec stat(group()) :: %{
  usage_reductions: non_neg_integer(),
  nr_throttled: non_neg_integer(),
  procs: non_neg_integer(),
  max_procs: non_neg_integer() | nil
}
```

Return host-only reduction, throttle and member counters for `group`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
