nexus-timer 1.4.3

High-performance timer wheel with O(1) insert and cancel
Documentation
# The `Wheel` API

## Construction

```rust
use std::time::Instant;
use nexus_timer::{Wheel, BoundedWheel, WheelBuilder};

let now = Instant::now();

// Unbounded (growable slab), default config
let wheel: Wheel<u64> = Wheel::unbounded(4096, now);

// Bounded (fixed capacity), default config
let wheel: BoundedWheel<u64> = BoundedWheel::bounded(4096, now);

// Custom config via builder
let wheel: Wheel<u64> = WheelBuilder::new()
    .tick_duration(std::time::Duration::from_micros(100))
    .slots_per_level(32)
    .clk_shift(4)           // 16x per level
    .num_levels(6)
    .unbounded(4096)
    .build(now);
```

The builder validates at `.build()` time — `slots_per_level` must be a power
of 2 and ≤ 64, `num_levels` must be ≤ 8, and the total range
(`slots_per_level << ((num_levels-1) * clk_shift)`) must not overflow u64.

`chunk_capacity` (unbounded) is the slab chunk size — how many entries the
underlying slab allocates per chunk as it grows. `capacity` (bounded) is
the total maximum number of concurrent timers.

## Scheduling

```rust
use std::time::{Duration, Instant};
use nexus_timer::{Wheel, TimerHandle};

let now = Instant::now();
let mut wheel: Wheel<OrderId> = Wheel::unbounded(1024, now);
# #[derive(Clone, Copy)] struct OrderId(u64);

// Cancellable timer — returns a handle
let handle: TimerHandle<OrderId> = wheel.schedule(
    now + Duration::from_millis(500),
    OrderId(42),
);

// Fire-and-forget — no handle, cannot be cancelled
wheel.schedule_forget(now + Duration::from_millis(250), OrderId(43));
```

`schedule` returns a `TimerHandle<T>`. The handle must be consumed — via
`cancel`, `free`, or `reschedule`. Dropping a handle is a programming error
(debug-assert fires).

Bounded wheels also expose `try_schedule` / `try_schedule_forget` which
return `Result<_, Full<T>>` on capacity exhaustion. Use these when you want
graceful handling rather than a panic.

## Cancelling

```rust
# use std::time::{Duration, Instant};
# use nexus_timer::Wheel;
# let now = Instant::now();
# let mut wheel: Wheel<u64> = Wheel::unbounded(1024, now);
# let handle = wheel.schedule(now + Duration::from_millis(500), 42u64);
// cancel: unlinks the entry, returns the value if the timer hadn't fired yet
match wheel.cancel(handle) {
    Some(value) => { /* timer was still pending, you get T back */ }
    None        => { /* timer already fired — handle is a "zombie" */ }
}
```

The handle is consumed either way. If the timer already fired during a
prior `poll`, the value was already delivered to the poll buffer; `cancel`
on a zombie handle just frees the slab entry.

## Free (convert to fire-and-forget)

```rust
# use std::time::{Duration, Instant};
# use nexus_timer::Wheel;
# let now = Instant::now();
# let mut wheel: Wheel<u64> = Wheel::unbounded(1024, now);
# let handle = wheel.schedule(now + Duration::from_millis(500), 42u64);
// Drop cancellation rights without cancelling the timer
wheel.free(handle);
```

Useful when you scheduled a timer cancellable-by-default but have decided
you no longer care about cancellation.

## Reschedule

```rust
# use std::time::{Duration, Instant};
# use nexus_timer::Wheel;
# let now = Instant::now();
# let mut wheel: Wheel<u64> = Wheel::unbounded(1024, now);
# let handle = wheel.schedule(now + Duration::from_millis(500), 42u64);
let handle = wheel.reschedule(handle, now + Duration::from_millis(1000));
```

Moves the entry from its current slot to the slot for the new deadline
*without reconstructing the value*. This is the fast path for
retransmission timers ("bump the TCP retransmit deadline each time we get
data").

Panics if called on a zombie handle (timer already fired).

## Polling

```rust
# use std::time::{Duration, Instant};
# use nexus_timer::Wheel;
let now = Instant::now();
let mut wheel: Wheel<u64> = Wheel::unbounded(1024, now);
wheel.schedule_forget(now + Duration::from_millis(5), 1);
wheel.schedule_forget(now + Duration::from_millis(10), 2);

let mut fired: Vec<u64> = Vec::with_capacity(64);
wheel.poll(now + Duration::from_millis(12), &mut fired);
// fired contains [1, 2] — all expired timer values
```

`poll(now, buf)` fires every expired timer and appends its value to `buf`.

`poll_with_limit(now, limit, buf)` is the budgeted version: fire up to
`limit` timers and return how many fired. Useful in a poll loop where you
want to cap the work done in one iteration to keep tail latency bounded.
If the limit is hit, the next call with the same `now` will resume
wherever you left off.

## `next_deadline`

```rust
# use std::time::{Duration, Instant};
# use nexus_timer::Wheel;
# let now = Instant::now();
# let mut wheel: Wheel<u64> = Wheel::unbounded(1024, now);
# wheel.schedule_forget(now + Duration::from_millis(10), 1);
let next: Option<Instant> = wheel.next_deadline();
// Use this to compute how long your event loop should sleep before polling again
```

Walks only *active* (non-empty) slots, so the cost is O(active_slots),
typically tens of cycles even for wheels holding thousands of timers.