# `Macaw.Data.Bounded`
[🔗](https://github.com/dcoai/macaw_data/blob/v0.5.3/lib/macaw/data/bounded.ex#L1)

One call in a monitored process of its own, its cost counted rather than timed: the
conformance kit's runner (spec/01 §9), ported from visualize's `Visualize.Bounded`.

The cost is the reductions the call's process spends, collections included, which a
loaded host does not change. A call that answers is judged by its own count, read as
its function returns; a call still running is read every 10 ms and killed at the first
reading over the cap. Liveness is a separate wall-clock bound, `timeout`, for a call
blocked in `receive`, which spends no reductions and so is never stopped by a cap.

Nothing is rescued: a raise or an exit is read from the process's `:DOWN`.

    iex> {:ok, 3, _spent} = Macaw.Data.Bounded.run(fn -> 1 + 2 end, timeout: 1_000)
    iex> Macaw.Data.Bounded.run(fn -> receive(do: (:never -> :ok)) end, timeout: 10)
    :hung

# `outcome`

```elixir
@type outcome() ::
  {:ok, term(), non_neg_integer()}
  | {:reductions, non_neg_integer()}
  | :hung
  | {:down, term()}
```

How a bounded call ended.

# `run`

```elixir
@spec run((-&gt; term()), keyword()) :: outcome()
```

`thunk` called in a process spawned with `spawn:` options and `:monitor`, the caller in
its `$callers`: `{:ok, value, reductions}`; `{:reductions, spent}` when it spent more
than `reductions:` (`nil`, no cap); `:hung` when it had not answered within `timeout:`
ms; `{:down, reason}` when it exited first, a heap limit's kill as `:killed`. A process
the caller kills is waited for, so nothing it does outlives the call.

---

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