# gizlang:task

Structured tasks. A task runs a closure alongside the rest of the program on the same thread (`thread` runs one on an OS thread of its own); sleeping, joining and I/O suspend only the calling task. A task never outlives the task that spawned it: when its work returns, its unjoined children are cancelled and awaited. Cancellation reaches a task at its next suspension point as fault 12.

```gizlang
import * as Task from "gizlang:task";
```

## Types

### `Fault`

```gizlang
type Fault = { code: i64; }
```

The runtime fault that ended a task: 12 when
it was cancelled, 13 when it waited for something that could never happen.

- `code`: `i64`

### `Task`

```gizlang
type Task<T>
```

A task that runs to a value of type T; `await` gives the value.

Opaque: create and use it through this module's functions.

### `Thread`

```gizlang
type Thread<T>
```

Work running on an OS thread of its own (`thread`).

Opaque: create and use it through this module's functions.

### `Channel`

```gizlang
type Channel<T>
```

A bounded first-in, first-out queue of values between tasks. It belongs to
the task that made it and closes, dropping what it still holds, when that
task ends.

Opaque: create and use it through this module's functions.

### `Cell`

```gizlang
type Cell<T>
```

One value shared by threads (`thread`), ArcSwap's role: `load` gives the
latest stored and `store` replaces it, and neither waits.

Opaque: create and use it through this module's functions.

### `Lease`

```gizlang
type Lease = { generation: i64; until: i64; }
```

A claim fence is monotone even when its wall clock moves backwards.
Persistence and authorization remain the caller's responsibility.

- `generation`: `i64`
- `until`: `i64`

### `Queue`

```gizlang
type Queue<T>
```

An unbounded queue for the tasks of any thread while the task that made it lives: any thread pushes, its reader
takes everything at once and may put a batch back in front. A short lock guards it (no suspension inside); a push
after close is dropped. Values are shared as on a crossing channel and may not hold Refs.

Opaque: create and use it through this module's functions.

### `LoadOrder`

```gizlang
type LoadOrder = "relaxed" | "acquire" | "seqCst"
```

The memory order of a load, as C11 and Rust name them. `seqCst` (the default) orders it with every other seqCst
operation; `acquire` makes the writes released before the value it reads visible; `relaxed` orders nothing.

### `StoreOrder`

```gizlang
type StoreOrder = "relaxed" | "release" | "seqCst"
```

The memory order of a store: `release` makes the writes before it visible to an acquire load of its value.

### `Order`

```gizlang
type Order = "relaxed" | "acquire" | "release" | "acqRel" | "seqCst"
```

The memory order of a read-modify-write (fetchAdd, compareExchange).

### `Atomic`

```gizlang
type Atomic
```

One i64 shared by the tasks of every thread, changed with C11 atomics (sequentially consistent unless an order is
given): no lock, no allocation after `create`. It uses 8 bytes until the process ends, and copies of it are the same
cell.

Opaque: create and use it through this module's functions.

### `Words`

```gizlang
type Words
```

A fixed number of i64 words that the tasks of every thread share and change in place, with no lock: a load sees
every store made before the store that wrote what it reads (acquire and release), and compareExchange is sequentially
consistent. Copies of it are the same words; the last copy to go frees them.

Opaque: create and use it through this module's functions.

### `Pair`

```gizlang
type Pair<A, B> = { first: A; second: B; }
```

The two values of an independent pair of tasks.

Opaque: create and use it through this module's functions.

## Functions

### `spawn`

```gizlang
function spawn<F>(work: F): Task<ReturnType<F>>
```

Start `work` as a task; `await` gives its result.

### `join`

```gizlang
function join<T>(task: Task<T>): T throws Fault
```

The task's value, or the fault that ended it. A value is taken once.

### `parallel`

```gizlang
function parallel<F>(count: i64, body: F): Vec<ReturnType<F>>
```

body(i) for every i in 0..count on the process's threads (as many as its
CPUs), the results in index order. The body may only compute and fail (no
I/O, console or shared state); what it captures is read-only while it runs.
A fault in any call is this call's fault.

### `fill`

```gizlang
function fill<F>(total: i64, chunk: i64, body: F): ReturnType<F>
```

One Vec of `total` items made on the process's threads: body(start) gives the
`chunk` items from `start` (the last chunk the rest), and each thread copies
its chunk into place, so the parts are never joined by one serial copy. The
items own nothing (numbers, bools, records of them); a chunk of another
length faults 1. The body is held to what `parallel`'s is.

### `thread`

```gizlang
function thread<F>(work: F): Thread<ReturnType<F>>
```

work(sys) on an OS thread of its own, in a World of its own: its own event
loop, tasks, handles and memory budget, and `sys` its own System, as a
process's main gets. It runs alongside every task of this thread; what work
captures is shared read-only (reference counts change atomically), and it
cannot reach this thread's Refs or handles (a captured handle is fault 14
there). When the task that started it ends, it cancels still-running work
at its next suspension point and waits for the thread to finish.

### `cores`

```gizlang
function cores(): i64
```

The CPUs this process may use (its affinity): the size of `parallel`'s pool
and of GIZLANG_WORKERS=auto. This observes affinity, CPU admission and the
environment; it cannot certify an environment-independent cached test.

Effects: read.

### `stackLeft`

```gizlang
function stackLeft(): i64
```

The bytes of stack the current task has left before a cyclic function faults with R009. A recursion whose
depth its input sets (a SQL function that calls itself) checks it and returns an
error instead of faulting.

Effects: read.

### `stackTop`

```gizlang
function stackTop(): u64
```

The address just above the running task's stack, or 0 on its thread's own stack: a collector that scans its
callers' frames conservatively (gizvm) reads up to it.

Effects: read.

### `cancel`

```gizlang
function cancel<T>(task: Task<T>): bool
```

Ask the task to stop: fault 12 at its next wait, so code
that never waits, such as a loop of arithmetic, runs on. False when it
already finished or was cancelled.

### `sleep`

```gizlang
function sleep(milliseconds: i64): bool
```

Wait `milliseconds` ms; true when the wait was not cut short.

Effects: fail, io.

### `pause`

```gizlang
function pause(): bool
```

Let every other ready task run once.

Effects: fail, io.

### `now`

```gizlang
function now(): i64
```

Milliseconds on a monotonic clock.

Effects: fail, io.

### `nanos`

```gizlang
function nanos(): i64
```

Nanoseconds on a monotonic clock: what JavaScript's performance.now and process.hrtime read (not replayed).

Effects: read.

### `claimLease`

```gizlang
function claimLease(previous: Lease, now: i64, duration: i64): Lease throws string
```

The lease after PREVIOUS: the next generation, held from NOW for DURATION and never ending before PREVIOUS ends. It
fails when a number is out of range.

Effects: fail.

### `retry`

```gizlang
function retry<F>(work: F, attempts: i64): ReturnType<F> throws Fault
```

Run `work` in a fresh task until it succeeds, at most `attempts` times;
the last fault when every attempt failed.

### `within`

```gizlang
function within<F>(milliseconds: i64, work: F): ReturnType<F> throws Fault
```

Run `work` in a fresh task for at most `milliseconds`; a task still running
then is cancelled, so the result is fault 12 once it waits (cancel): a loop
that never waits is not stopped, and this does not return until it ends.

### `channel`

```gizlang
function channel<T>(capacity: i64): Channel<T>
```

A channel holding at most `capacity` (at least 1) values.

### `crossing`

```gizlang
function crossing<T>(capacity: i64): Channel<T>
```

A channel between threads: the tasks of any thread (`thread`) may send,
receive and close while the task that made it lives. A value sent is marked
shared (counts change atomically), so the receiver may keep or change it
(a write copies a buffer someone else still holds); values may not hold Refs.
A task waiting on it is never reported as deadlocked: another thread may
still send or close.

### `send`

```gizlang
function send<T>(queue: Channel<T>, value: T): bool
```

Move `value` in, waiting while the channel is full; false (and the value is
dropped) when it is closed.

### `trySend`

```gizlang
function trySend<T>(queue: Channel<T>, value: T): bool
```

Move `value` in without waiting. False drops this value when the channel is
full or closed; it never enqueues a value after returning false.

### `respond`

```gizlang
function respond<T>(queue: Channel<T>, value: T): bool
```

Complete an asynchronous response without waiting. False drops the value
when the recipient is full, closed or its owning task has ended. Expired
recipients grant no access to a reused channel slot. Ordinary sends retain
their stale-handle fault contract.

### `receive`

```gizlang
function receive<T>(queue: Channel<T>): Option<T>
```

The oldest value, waiting for one; none once the channel is closed and empty.

### `tryReceive`

```gizlang
function tryReceive<T>(queue: Channel<T>): Option<T>
```

The oldest value without waiting; none when nothing is queued (or the channel is closed and empty). A Ready set
that watches a crossing channel (Ready.channel) drains it with this.

### `handOff`

```gizlang
function handOff<T>(queue: Channel<T>, value: mut T): bool
```

Move VALUE in, waiting while the channel is full, and leave VALUE empty (zero) for the caller to assign again before
reading it: a whole record (the JS Heap at each coroutine switch) moves without the copy send makes of a value it
borrows. False (and the value dropped) when the channel is closed.

### `receiveMoved`

```gizlang
function receiveMoved<T>(queue: Channel<T>): T
```

The oldest value, waiting for one, moved out to the caller (matching receive's Option copies it); a fault once the
channel is closed and empty.

### `exchange`

```gizlang
function exchange<T>(to: Channel<T>, back: Channel<T>, value: mut T): bool
```

handOff of VALUE to TO, then receiveMoved from BACK into VALUE: each a copy of its bytes, where the two calls copy a
large record field by field several times (4 µs of each JS await for the 4 KB Heap, 10/17). Faults once BACK is
closed and empty. False when TO was closed (VALUE was dropped).

### `close`

```gizlang
function close<T>(queue: Channel<T>): bool
```

No more sends; receivers drain what is queued. False when already closed.

### `cell`

```gizlang
function cell<T>(initial: T): Cell<T>
```

A cell holding `initial`, for the tasks of any thread while the task that
made it lives. As on a crossing channel, values are marked shared and may not
hold Refs; a writer's `store` of a new snapshot never waits for readers.

### `newQueue`

```gizlang
function newQueue<T>(): Queue<T>
```

An empty queue between tasks.

### `atomic`

```gizlang
function atomic(initial: i64): Atomic
```

A new atomic holding `initial`.

Effects: io.

### `atomicGlobal`

```gizlang
function atomicGlobal(name: string): Atomic
```

The one atomic of `name` in this process, made with value 0 on first use
(thread-safe): every thread gets the same cell. The lookup takes a lock, so
keep the result and do not call `global` on a hot path.

Effects: io.

### `words`

```gizlang
function words(count: i64): Words
```

COUNT new words, each 0.

Effects: fail, io.

### `zip`

```gizlang
function zip<F, G>(first: F, second: G): Pair<ReturnType<F>, ReturnType<G>> throws Fault
```

Start both jobs together and join both, even when one fails.
A task fault stays a Fault; a Result returned by a job stays a Result.

## Methods

### `Thread.join`

```gizlang
function Thread.join<T>(self: Thread<T>): T throws Fault
```

The thread's value, or the fault that ended it; waiting suspends only the
calling task. A value is taken once.

### `Cell.load`

```gizlang
function Cell.load<T>(self: Cell<T>): T
```

The latest value stored (a shared copy: changing it copies what it changes).

### `Cell.store`

```gizlang
function Cell.store<T>(self: Cell<T>, value: T): bool
```

Replace the value; readers that loaded the old one keep it. Like loading,
it faults once the task that made the cell has ended.

### `Cell.close`

```gizlang
function Cell.close<T>(self: Cell<T>): bool
```

Drops the value now, not when the task that made the cell ends: a long task that makes cells for data it later
retires (a cold segment's columns) gives their memory back. A load or store after it faults. False when already
closed.

### `Queue.push`

```gizlang
function Queue.push<T>(self: Queue<T>, value: T): bool
```

VALUE at the end; false (dropped) once the queue is closed.

### `Queue.take`

```gizlang
function Queue.take<T>(self: Queue<T>): Vec<T>
```

Everything queued, oldest first; the queue is empty after.

### `Queue.putBack`

```gizlang
function Queue.putBack<T>(self: Queue<T>, values: Vec<T>): void
```

VALUES back in front, in their order (a reader that took more than it used).

### `Queue.shut`

```gizlang
function Queue.shut<T>(self: Queue<T>): Vec<T>
```

No more pushes: what is queued, which nobody takes after this.

### `Atomic.load`

```gizlang
function Atomic.load(self: Atomic, order: LoadOrder = "seqCst"): i64
```

The current value.

Effects: io.

### `Atomic.store`

```gizlang
function Atomic.store(self: Atomic, value: i64, order: StoreOrder = "seqCst"): bool
```

Replace the value. Always true.

Effects: io.

### `Atomic.fetchAdd`

```gizlang
function Atomic.fetchAdd(self: Atomic, delta: i64, order: Order = "seqCst"): i64
```

Add `delta` (wrapping on overflow) and return the value from before.

Effects: io.

### `Atomic.compareExchange`

```gizlang
function Atomic.compareExchange(self: Atomic, expected: i64, desired: i64, order: Order = "seqCst"): bool
```

A failed exchange is a load with ORDER's acquire part.

Effects: io.

### `Words.count`

```gizlang
function Words.count(self: Words): i64
```

How many words there are.

### `Words.load`

```gizlang
function Words.load(self: Words, i: i64): i64
```

The value of word I.

Effects: fail, io.

### `Words.store`

```gizlang
function Words.store(self: Words, i: i64, value: i64): bool
```

Sets word I to VALUE. Always true.

Effects: fail, io.

### `Words.compareExchange`

```gizlang
function Words.compareExchange(self: Words, i: i64, expected: i64, desired: i64): bool
```

Sets word I to DESIRED only when it holds EXPECTED; true when it did.

Effects: fail, io.

