Macaw.Data.Bounded (macaw_data v0.5.3)

Copy Markdown View Source

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

Summary

Types

How a bounded call ended.

Functions

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.

Types

outcome()

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

How a bounded call ended.

Functions

run(thunk, opts)

@spec run((-> 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.