# Threads and Polling

> UCall for Rust

The crate starts no threads and needs no async runtime: every callback runs on a thread the application lent to a polling call.

- A route handler runs on the thread inside `take_call` or `take_calls` for the event loop that received the request.
- A batch handler runs on the thread inside `take_batch` or `take_batches` for its endpoint, never on an event loop.
- A server's peer authorizer runs on the polling thread completing the handshake, and a client's on the client's own thread inside `take_completed`, `call`, `get` or `post`.

Each event loop and each batch endpoint has one polling owner at a time, and a second thread polling it concurrently gets `Status::Contended`.
`take_calls` and `take_batches` run until `Server::stop`, while `take_call` and `take_batch` return after one round, waiting up to their timeout, so a loop of them interleaves polling with other work on the same thread.
`Server::stop` works from any thread, handlers included, wakes every polling thread, and dropping the `Server` stops it too.
The first stop drains, answering every request already held before its connection closes, and a second one cuts the replies still in flight.
An interface accepts on its own number of event loops, one by default, and the server runs the largest of those counts.

Registration takes `&mut Server`, and polling, stopping and statistics take `&Server`, so the borrow checker orders setup before serving.
A `Request` and a `Response` move between threads, while a `Client` stays on the thread that created it.
Every thread that polls, replies or reads must run on a CPU supporting the CPU class the server or client resolved at start, so `CPUClass::Serial` is the safe choice on machines mixing CPU generations.

`use ucall::Polling;`

`use ucall::CPUClass;`

## Polling

What [`Server::take_call`](https://www.unum.cloud/docs/ucall/rust/serving.md#take_call) found of its event loop.

```rust
pub enum Polling
```

- `Serving`: The loop serves, or drains what it holds after a stop.
- `Retired`: The loop drained or cut everything after [`Server::stop`](https://www.unum.cloud/docs/ucall/rust/serving.md#stop), so a caller polling in slices
stops.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, [`Debug`](https://www.unum.cloud/docs/ucall/rust/serving.md#Debug)

## CPUClass

The CPU kernels a server or client runs, from the portable [`Serial`](#Serial) up, where [`None`](https://www.unum.cloud/docs/ucall/rust/noise-keys.md#None) takes what the constructing thread's CPU offers.

```rust
pub enum CPUClass
```

A class is a ceiling: the newest compiled class under it runs, failing with
[`Status::Unsupported`](https://www.unum.cloud/docs/ucall/rust/errors.md#Unsupported) where the CPU does not run it. Every thread that later polls, replies, or
reads must run on a CPU supporting the class resolved at construction, and [`Serial`](#Serial) is the
conservative choice where they differ. Prints and parses its stable name, like "intel-icelake".

- `Serial` = `1`: Portable kernels that run on any CPU.
- `IntelHaswell` = `2`: x86 cores from Intel Haswell on.
- `IntelSkylake` = `3`: x86 server cores from Intel Skylake on.
- `IntelIcelake` = `4`: x86 server cores from Intel Ice Lake on.
- `IntelAlder` = `5`: x86 hybrid cores from Intel Alder Lake on.
- `AWSG2` = `6`: Arm cores from AWS Graviton 2 on.
- `AWSG5` = `7`: Arm server cores from AWS Graviton 5 on.
- `Monoversioned` = `8`: The one class of a monoversioned build, with every capability it compiled.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, [`Debug`](https://www.unum.cloud/docs/ucall/rust/serving.md#Debug), `Hash`, `Display`, `FromStr`

