fibre 0.5.8

High-performance, safe, memory-efficient sync/async channels built for real-time, low-overhead communication in concurrent Rust applications.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# API Reference: `fibre`

## 1. Core Concepts

`fibre` is a library of high-performance, memory-efficient, and flexible channels for concurrent programming in Rust. It provides specialized implementations for common producer/consumer patterns.

*   **Specialized Channels**: The library offers distinct channel types, each optimized for a specific concurrency pattern to ensure maximum performance and low overhead:
    *   `spsc`: **S**ingle-**P**roducer, **S**ingle-**C**onsumer. The fastest channel for 1-to-1 communication, implemented with a lock-free ring buffer.
    *   `mpsc`: **M**ulti-**P**roducer, **S**ingle-**C**onsumer. Ideal for collecting work from many sources into one processor. Supports both bounded and unbounded modes.
    *   `spmc`: **S**ingle-**P**roducer, **M**ulti-**C**onsumer. A "broadcast" or "fan-out" channel where one producer sends cloned messages to many consumers. It also includes a `topic`-based pub/sub variant.
    *   `mpmc`: **M**ulti-**P**roducer, **M**ulti-**C**onsumer. The most flexible channel for many-to-many communication, supporting both bounded and unbounded modes.
    *   `oneshot`: A channel for sending a single value, exactly once.

*   **Hybrid Sync/Async Model**: A core feature of `fibre` is the seamless interoperability between synchronous (`std::thread`) and asynchronous (`tokio`) code. All `Sender` and `Receiver` handles provide `to_sync()` or `to_async()` methods that perform a zero-cost conversion. This allows, for example, a synchronous thread to send data to an asynchronous task on the same channel.

*   **Sender and Receiver Handles**: Interaction with channels is done through `Sender` and `Receiver` handles. These handles control access and lifetime. When all `Sender` handles for a channel are dropped, it becomes "disconnected." When all `Receiver` handles are dropped, it becomes "closed." Handle cloning semantics vary by channel type (e.g., `mpmc::Sender` is `Clone`, but `spsc::BoundedSyncSender` is not).

*   **Stream API**: All asynchronous receivers that can yield multiple items (`mpmc::AsyncReceiver`, `mpsc::UnboundedAsyncReceiver`, `mpsc::BoundedAsyncReceiver`, `spmc::AsyncReceiver`, `spsc::AsyncBoundedSpscReceiver`, `spmc::topic::AsyncTopicReceiver`) implement the `futures::Stream` trait, allowing them to be used with the rich combinator library from `futures-util`.

## 2. Error Handling

`fibre` uses a consistent set of error types to signal the outcome of channel operations.

### `TrySendError<T>`

Returned by non-blocking `try_send` methods.

*   **Enum Variants**:
    *   `Full(T)`: The channel is full and cannot accept an item.
    *   `Closed(T)`: The channel is closed because the receiver(s) have dropped.
    *   `Sent(T)`: (Oneshot only) A value has already been sent on this channel.
*   **Methods**:
    *   `pub fn into_inner(self) -> T`: Consumes the error, returning the inner value that could not be sent.

### `SendError`

Returned by blocking or `async` `send` methods.

*   **Enum Variants**:
    *   `Closed`: The channel is closed because the receiver(s) have dropped.
    *   `Sent`: (Oneshot only) A value has already been sent.

### `TryRecvError`

Returned by non-blocking `try_recv` methods.

*   **Enum Variants**:
    *   `Empty`: The channel is currently empty but still active.
    *   `Disconnected`: The channel is empty and all senders have dropped.

### `RecvError`

Returned by blocking or `async` `recv` methods.

*   **Enum Variants**:
    *   `Disconnected`: The channel is empty and all senders have dropped.

### `RecvErrorTimeout`

Returned by `recv_timeout` methods.

*   **Enum Variants**:
    *   `Disconnected`: The channel became disconnected during the wait.
    *   `Timeout`: The timeout elapsed before an item could be received.

### `CloseError`

A unit-like struct returned when `close()` is called on an already-closed handle.

### `TrySendBatchError<T>`

Returned by non-blocking `try_send_batch` methods. Carries partial-progress state so no owned value is silently dropped.

*   **Fields**:
    *   `sent: usize`: The number of items successfully sent before the operation stopped.
    *   `unsent: Vec<T>`: The items that were not sent, in their original order.
    *   `reason: BatchSendErrorReason`: Why the batch stopped early.
*   **Methods**:
    *   `pub fn into_unsent(self) -> Vec<T>`: Consumes the error, returning the unsent items.

### `SendBatchError<T>`

Returned by blocking or `async` `send_batch` methods. The only failure cause is channel closure.

*   **Fields**:
    *   `sent: usize`: The number of items successfully sent before the channel closed.
    *   `unsent: Vec<T>`: The items that were not sent, in their original order.
*   **Methods**:
    *   `pub fn into_unsent(self) -> Vec<T>`: Consumes the error, returning the unsent items.

### `BatchSendErrorReason`

*   **Enum Variants**:
    *   `Full`: The channel was full (or, for a rendezvous channel, no receiver was ready).
    *   `Closed`: The channel is closed because all receivers have been dropped.

### Batch Operation Semantics

All core channels (`spsc`, `mpsc`, `spmc`, `mpmc`) provide eight batch operations per handle pair with uniform semantics. The `oneshot` and `spmc::topic` channels do not provide batch operations.

*   **By-value send** (`try_send_batch(items: Vec<T>)`, `send_batch(items: Vec<T>)`): `Ok(n)` means *every* item was sent. On interruption, the error carries the count sent and the unsent remainder.
*   **In-place send** (`try_send_batch_mut(&mut Vec<T>)`, `send_batch_mut(&mut Vec<T>)`): sent items are drained from the *front* of the caller's vector; unsent items always remain in it. `Err(SendError::Closed)` from a `try` variant means zero items were sent by that call.
*   **By-value receive** (`try_recv_batch(max)`, `recv_batch(max)`): returns 1..=`max` items in FIFO order. Blocking/async variants wait until *at least one* item is available, then drain up to `max` without further waiting.
*   **In-place receive** (`try_recv_batch_mut(&mut Vec<T>, max)`, `recv_batch_mut(&mut Vec<T>, max)`): appends to the *end* of the caller's vector and returns the count appended.
*   **Edge cases**: an empty input vector or `max == 0` returns `Ok(0)` / an empty vector immediately, with no channel interaction.
*   **Cancellation**: dropping a pending by-value async send-batch future drops the unsent remainder (consistent with the single-item send futures); the `_mut` send futures are cancel-safe (unsent items remain in the caller's vector). All batch receive futures are cancel-safe.

## 3. Module `fibre::oneshot`

A channel for sending a single value from one of potentially many senders to a single receiver.

### Functions

*   `pub fn oneshot<T>() -> (Sender<T>, Receiver<T>)`

### Struct `Sender<T>`

The sending side of a oneshot channel. Can be cloned. `send` consumes the handle.

*   **Methods**:
    *   `pub fn send(self, value: T) -> Result<(), TrySendError<T>>`
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn is_sent(&self) -> bool`

### Struct `Receiver<T>`

The receiving side of a oneshot channel. Cannot be cloned.

*   **Methods**:
    *   `pub fn recv(&self) -> ReceiveFuture<'_, T>`
    *   `pub fn try_recv(&self) -> Result<T, TryRecvError>`
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`

## 4. Module `fibre::spsc`

A high-performance, lock-free, bounded channel for one producer and one consumer.

### Functions

*   `pub fn bounded_sync<T: Send>(capacity: usize) -> (BoundedSyncSender<T>, BoundedSyncReceiver<T>)`
*   `pub fn bounded_async<T: Send>(capacity: usize) -> (AsyncBoundedSpscSender<T>, AsyncBoundedSpscReceiver<T>)`

### Struct `BoundedSyncSender<T>`

The synchronous, non-cloneable sending handle.

*   **Methods**:
    *   `pub fn to_async(self) -> AsyncBoundedSpscSender<T>`
    *   `pub fn try_send(&self, item: T) -> Result<(), TrySendError<T>>`
    *   `pub fn send(&self, item: T) -> Result<(), SendError>`
    *   `pub fn try_send_batch(&self, items: Vec<T>) -> Result<usize, TrySendBatchError<T>>`
    *   `pub fn send_batch(&self, items: Vec<T>) -> Result<usize, SendBatchError<T>>`: Blocks until all items are sent.
    *   `pub fn try_send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>`: Drains sent items from the front of `items`.
    *   `pub fn send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>`: Blocking in-place batch send.
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn capacity(&self) -> usize`
    *   `pub fn len(&self) -> usize`
    *   `pub fn is_empty(&self) -> bool`
    *   `pub fn is_full(&self) -> bool`

### Struct `BoundedSyncReceiver<T>`

The synchronous, non-cloneable receiving handle.

*   **Methods**:
    *   `pub fn to_async(self) -> AsyncBoundedSpscReceiver<T>`
    *   `pub fn try_recv(&self) -> Result<T, TryRecvError>`
    *   `pub fn recv(&self) -> Result<T, RecvError>`
    *   `pub fn recv_timeout(&mut self, timeout: std::time::Duration) -> Result<T, RecvErrorTimeout>`
    *   `pub fn try_recv_batch(&self, max: usize) -> Result<Vec<T>, TryRecvError>`
    *   `pub fn recv_batch(&self, max: usize) -> Result<Vec<T>, RecvError>`: Blocks until at least one item, returns 1..=max.
    *   `pub fn try_recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, TryRecvError>`: Appends to `out`.
    *   `pub fn recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, RecvError>`: Blocking in-place batch receive.
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `is_closed`, `capacity`, `len`, `is_empty`, `is_full`

### Struct `AsyncBoundedSpscSender<T>`

The asynchronous, non-cloneable sending handle.

*   **Methods**:
    *   `pub fn to_sync(self) -> BoundedSyncSender<T>`
    *   `pub fn send(&self, item: T) -> SendFuture<'_, T>`
    *   `pub fn send_batch(&self, items: Vec<T>) -> SendBatchFuture<'_, T>`: Resolves with `Result<usize, SendBatchError<T>>`.
    *   `pub fn send_batch_mut<'a>(&'a self, items: &'a mut Vec<T>) -> SendBatchMutFuture<'a, T>`: Cancel-safe; resolves with `Result<usize, SendError>`.
    *   `try_send`, `try_send_batch`, `try_send_batch_mut`, `close`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`

### Struct `AsyncBoundedSpscReceiver<T>`

The asynchronous, non-cloneable receiving handle. Implements `futures::Stream`.

*   **Methods**:
    *   `pub fn to_sync(self) -> BoundedSyncReceiver<T>`
    *   `pub fn recv(&self) -> ReceiveFuture<'_, T>`
    *   `pub fn recv_batch(&self, max: usize) -> RecvBatchFuture<'_, T>`: Resolves with `Result<Vec<T>, RecvError>`.
    *   `pub fn recv_batch_mut<'a>(&'a self, out: &'a mut Vec<T>, max: usize) -> RecvBatchMutFuture<'a, T>`: Resolves with `Result<usize, RecvError>`.
    *   `try_recv`, `try_recv_batch`, `try_recv_batch_mut`, `close`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`

## 5. Module `fibre::mpsc`

An optimized channel for multiple producers and one consumer.

*Note: The `mpsc` module provides both bounded and unbounded channels. The types are prefixed accordingly (e.g., `UnboundedSender`, `BoundedSender`) and are all exported directly from the `mpsc` module.*

### Functions

*   `pub fn unbounded<T: Send>() -> (UnboundedSender<T>, UnboundedReceiver<T>)`
*   `pub fn unbounded_async<T: Send>() -> (UnboundedAsyncSender<T>, UnboundedAsyncReceiver<T>)`
*   `pub fn bounded<T: Send>(capacity: usize) -> (BoundedSender<T>, BoundedReceiver<T>)`
*   `pub fn bounded_async<T: Send>(capacity: usize) -> (BoundedAsyncSender<T>, BoundedAsyncReceiver<T>)`

### Unbounded MPSC Types

*   **Struct `UnboundedSender<T: Send>`**: A cloneable, sync handle for the unbounded channel.
    *   `send(&self, value: T) -> Result<(), SendError>`: Non-blocking send.
    *   `send_batch(&self, items: Vec<T>) -> Result<usize, SendBatchError<T>>`: Never blocks (unbounded); one length update + one wake per batch.
    *   `try_send_batch(&self, items: Vec<T>) -> Result<usize, TrySendBatchError<T>>`
    *   `send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>` / `try_send_batch_mut(...)`: In-place variants.
    *   Methods: `try_send`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `to_async`.
*   **Struct `UnboundedReceiver<T: Send>`**: A non-cloneable, sync handle.
    *   `recv(&self) -> Result<T, RecvError>`: Blocks if empty.
    *   `recv_timeout(&self, timeout: std::time::Duration) -> Result<T, RecvErrorTimeout>`
    *   `recv_batch(&self, max: usize) -> Result<Vec<T>, RecvError>` / `try_recv_batch(&self, max: usize) -> Result<Vec<T>, TryRecvError>`
    *   `recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, RecvError>` / `try_recv_batch_mut(...)`: Append to `out`.
    *   Methods: `try_recv`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `to_async`.
*   **Struct `UnboundedAsyncSender<T: Send>`**: A cloneable, async handle.
    *   `send(&self, value: T) -> UnboundedSendFuture<'_, T>`: Non-blocking future.
    *   `send_batch(&self, items: Vec<T>) -> UnboundedSendBatchFuture<'_, T>` / `send_batch_mut(...) -> UnboundedSendBatchMutFuture<'_, T>`: Complete on first poll (unbounded).
    *   Methods: `try_send`, `try_send_batch`, `try_send_batch_mut`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `to_sync`.
*   **Struct `UnboundedAsyncReceiver<T: Send>`**: A non-cloneable, async handle. Implements `futures::Stream`.
    *   `recv(&self) -> UnboundedRecvFuture<'_, T>`: Returns a future that waits for an item.
    *   `recv_batch(&self, max: usize) -> UnboundedRecvBatchFuture<'_, T>` / `recv_batch_mut(...) -> UnboundedRecvBatchMutFuture<'_, T>`: Cancel-safe batch receives.
    *   Methods: `try_recv`, `try_recv_batch`, `try_recv_batch_mut`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `to_sync`.

### Bounded MPSC Types

*   **Struct `BoundedSender<T: Send>`**: A cloneable, sync handle for the bounded channel.
    *   `send(&self, value: T) -> Result<(), SendError>`: Blocks if full.
    *   `send_batch(&self, items: Vec<T>) -> Result<usize, SendBatchError<T>>`: Acquires capacity permits in bulk; blocks for the remainder.
    *   `try_send_batch(&self, items: Vec<T>) -> Result<usize, TrySendBatchError<T>>`: Sends as many items as permits are available.
    *   `send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>` / `try_send_batch_mut(...)`: In-place variants.
    *   Methods: `try_send`, `clone`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `capacity`, `is_full`, `to_async`.
*   **Struct `BoundedReceiver<T: Send>`**: A non-cloneable, sync handle.
    *   `recv(&self) -> Result<T, RecvError>`: Blocks if empty.
    *   `recv_timeout(&self, timeout: std::time::Duration) -> Result<T, RecvErrorTimeout>`
    *   `recv_batch(&self, max: usize) -> Result<Vec<T>, RecvError>` / `try_recv_batch(&self, max: usize) -> Result<Vec<T>, TryRecvError>`: Capacity permits are returned in one bulk release per batch.
    *   `recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, RecvError>` / `try_recv_batch_mut(...)`: Append to `out`.
    *   Methods: `try_recv`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `capacity`, `is_full`, `to_async`.
*   **Struct `BoundedAsyncSender<T: Send>`**: A cloneable, async handle.
    *   `send(&self, value: T) -> BoundedSendFuture<'_, T>`: Returns a future that waits for capacity.
    *   `send_batch(&self, items: Vec<T>) -> BoundedSendBatchFuture<'_, T>` / `send_batch_mut(...) -> BoundedSendBatchMutFuture<'_, T>`: Acquire permits in bulk, re-arming for the remainder.
    *   Methods: `try_send`, `try_send_batch`, `try_send_batch_mut`, `clone`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `capacity`, `is_full`, `to_sync`.
*   **Struct `BoundedAsyncReceiver<T: Send>`**: A non-cloneable, async handle. Implements `futures::Stream`.
    *   `recv(&self) -> BoundedRecvFuture<'_, T>`: Returns a future that waits for an item.
    *   `recv_batch(&self, max: usize) -> BoundedRecvBatchFuture<'_, T>` / `recv_batch_mut(...) -> BoundedRecvBatchMutFuture<'_, T>`: Cancel-safe batch receives.
    *   Methods: `try_recv`, `try_recv_batch`, `try_recv_batch_mut`, `is_closed`, `close`, `sender_count`, `len`, `is_empty`, `capacity`, `is_full`, `to_sync`.

## 6. Module `fibre::spmc`

A broadcast-style channel for one producer and multiple consumers. `T` must be `Send + Clone`.

### Functions

*   `pub fn bounded<T: Send + Clone>(capacity: usize) -> (Sender<T>, Receiver<T>)`
*   `pub fn bounded_async<T: Send + Clone>(capacity: usize) -> (AsyncSender<T>, AsyncReceiver<T>)`

### Struct `Sender<T: Send + Clone>`

The synchronous, non-cloneable sending handle.

*   **Methods**:
    *   `send(&self, value: T) -> Result<(), SendError>`: Blocks if any consumer's buffer is full.
    *   `try_send(&self, value: T) -> Result<(), TrySendError<T>>`
    *   `send_batch(&self, items: Vec<T>) -> Result<usize, SendBatchError<T>>`: Capacity is bounded by the slowest consumer; one head update + one coalesced waker pass per batch.
    *   `try_send_batch(&self, items: Vec<T>) -> Result<usize, TrySendBatchError<T>>`
    *   `send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>` / `try_send_batch_mut(...)`: In-place variants.
    *   `close(&mut self) -> Result<(), CloseError>`
    *   `to_async`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `Receiver<T: Send + Clone>`

The synchronous, cloneable receiving handle.

*   **Methods**:
    *   `recv(&self) -> Result<T, RecvError>`: Blocks if this consumer's buffer is empty.
    *   `recv_timeout(&self, timeout: std::time::Duration) -> Result<T, RecvErrorTimeout>`
    *   `try_recv(&self) -> Result<T, TryRecvError>`
    *   `recv_batch(&self, max: usize) -> Result<Vec<T>, RecvError>` / `try_recv_batch(&self, max: usize) -> Result<Vec<T>, TryRecvError>`: Each consumer receives (clones) every broadcast item; the consumer tail advances once per batch.
    *   `recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, RecvError>` / `try_recv_batch_mut(...)`: Append to `out`.
    *   `close(&self) -> Result<(), CloseError>`
    *   `to_async`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `AsyncSender<T: Send + Clone>`

The asynchronous, non-cloneable sending handle.

*   **Methods**:
    *   `send(&self, value: T) -> SendFuture<'_, T>`
    *   `send_batch(&self, items: Vec<T>) -> SendBatchFuture<'_, T>` / `send_batch_mut(...) -> SendBatchMutFuture<'_, T>`
    *   `try_send`, `try_send_batch`, `try_send_batch_mut`, `close(&mut self)`, `to_sync`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `AsyncReceiver<T: Send + Clone>`

The asynchronous, cloneable receiving handle. Implements `futures::Stream`.

*   **Methods**:
    *   `recv(&self) -> RecvFuture<'_, T>`
    *   `recv_batch(&self, max: usize) -> RecvBatchFuture<'_, T>` / `recv_batch_mut(...) -> RecvBatchMutFuture<'_, T>`
    *   `try_recv`, `try_recv_batch`, `try_recv_batch_mut`, `close`, `to_sync`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

## 7. Module `fibre::mpmc`

A flexible, lock-based channel for many producers and many consumers.

### Functions

*   `pub fn bounded<T: Send>(capacity: usize) -> (Sender<T>, Receiver<T>)`
*   `pub fn bounded_async<T: Send>(capacity: usize) -> (AsyncSender<T>, AsyncReceiver<T>)`
*   `pub fn unbounded<T: Send>() -> (Sender<T>, Receiver<T>)`
*   `pub fn unbounded_async<T: Send>() -> (AsyncSender<T>, AsyncReceiver<T>)`

### Struct `Sender<T: Send>`

The synchronous, cloneable sending handle.

*   **Methods**:
    *   `send(&self, item: T) -> Result<(), SendError>`: Blocks if the channel is full.
    *   `try_send(&self, item: T) -> Result<(), TrySendError<T>>`
    *   `send_batch(&self, items: Vec<T>) -> Result<usize, SendBatchError<T>>`: The whole batch is processed under one lock acquisition; satisfied receivers are woken in one coalesced pass after the lock is released.
    *   `try_send_batch(&self, items: Vec<T>) -> Result<usize, TrySendBatchError<T>>`
    *   `send_batch_mut(&self, items: &mut Vec<T>) -> Result<usize, SendError>` / `try_send_batch_mut(...)`: In-place variants.
    *   `close(&self) -> Result<(), CloseError>`
    *   `to_async`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `Receiver<T: Send>`

The synchronous, cloneable receiving handle.

*   **Methods**:
    *   `recv(&self) -> Result<T, RecvError>`: Blocks if the channel is empty.
    *   `recv_timeout(&self, timeout: std::time::Duration) -> Result<T, RecvErrorTimeout>`
    *   `try_recv(&self) -> Result<T, TryRecvError>`
    *   `recv_batch(&self, max: usize) -> Result<Vec<T>, RecvError>` / `try_recv_batch(&self, max: usize) -> Result<Vec<T>, TryRecvError>`: For rendezvous channels, payloads are extracted directly from waiting senders.
    *   `recv_batch_mut(&self, out: &mut Vec<T>, max: usize) -> Result<usize, RecvError>` / `try_recv_batch_mut(...)`: Append to `out`.
    *   `close(&self) -> Result<(), CloseError>`
    *   `to_async`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `AsyncSender<T: Send>`

The asynchronous, cloneable sending handle.

*   **Methods**:
    *   `send(&self, item: T) -> SendFuture<'_, T>`
    *   `send_batch(&self, items: Vec<T>) -> SendBatchFuture<'_, T>` / `send_batch_mut(...) -> SendBatchMutFuture<'_, T>`: The `_mut` variant is cancel-safe and recovers a parked rendezvous payload on drop.
    *   `try_send`, `try_send_batch`, `try_send_batch_mut`, `close`, `to_sync`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

### Struct `AsyncReceiver<T: Send>`

The asynchronous, cloneable receiving handle. Implements `futures::Stream`.

*   **Methods**:
    *   `recv(&self) -> RecvFuture<'_, T>`
    *   `recv_batch(&self, max: usize) -> RecvBatchFuture<'_, T>` / `recv_batch_mut(...) -> RecvBatchMutFuture<'_, T>`
    *   `try_recv`, `try_recv_batch`, `try_recv_batch_mut`, `close`, `to_sync`, `is_closed`, `capacity`, `len`, `is_empty`, `is_full`.

## 8. Module `fibre::spmc::topic`

A multi-consumer "topic" or "publish-subscribe" channel. This channel allows a single producer to broadcast messages to multiple consumers, where each consumer subscribes to specific "topics". A message sent to a topic is delivered to all consumers subscribed to that topic.

*   **Behavior**:
    *   **Topic-Based Filtering**: Consumers only receive messages for topics they explicitly subscribe to.
    *   **Non-Blocking Sender**: The sender is not blocked by slow consumers. If a consumer's internal message buffer (mailbox) is full, new messages for that consumer are dropped, ensuring the sender and other consumers are not impacted.
    *   **`Clone` Requirement**: Since a message can be delivered to multiple subscribers, the message type `T` and topic key `K` must implement `Clone`.
    *   **Sync/Async Agnostic**: Full interoperability between sync and async code.

### Functions

*   `pub fn channel<K, T>(mailbox_capacity: usize) -> (TopicSender<K, T>, TopicReceiver<K, T>)`
*   `pub fn channel_async<K, T>(mailbox_capacity: usize) -> (AsyncTopicSender<K, T>, AsyncTopicReceiver<K, T>)`

### Struct `TopicSender<K, T>`

The synchronous, cloneable sending handle.

*   **Methods**:
    *   `pub fn send(&self, topic: K, value: T) -> Result<(), SendError>`: Non-blocking send. Drops message for slow consumers.
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn to_async(self) -> AsyncTopicSender<K, T>`

### Struct `TopicReceiver<K, T>`

The synchronous, cloneable receiving handle.

*   **Methods**:
    *   `pub fn subscribe(&self, topic: K)`
    *   `pub fn unsubscribe<Q: ?Sized>(&self, topic: &Q)`
    *   `pub fn recv(&self) -> Result<(K, T), RecvError>`: Blocks if this receiver's mailbox is empty.
    *   `pub fn try_recv(&self) -> Result<(K, T), TryRecvError>`
    *   `pub fn recv_timeout(&self, timeout: std::time::Duration) -> Result<(K, T), RecvErrorTimeout>`
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn capacity(&self) -> usize`: Returns the capacity of this receiver's mailbox.
    *   `pub fn is_empty(&self) -> bool`: Returns `true` if this receiver's mailbox is empty.
    *   `pub fn to_async(self) -> AsyncTopicReceiver<K, T>`

### Struct `AsyncTopicSender<K, T>`

The asynchronous, cloneable sending handle.

*   **Methods**:
    *   `pub fn send(&self, topic: K, value: T) -> Result<(), SendError>`: Non-blocking, fire-and-forget send.
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn to_sync(self) -> TopicSender<K, T>`

### Struct `AsyncTopicReceiver<K, T>`

The asynchronous, cloneable receiving handle. Implements `futures::Stream`.

*   **Methods**:
    *   `pub fn subscribe(&self, topic: K)`
    *   `pub fn unsubscribe<Q: ?Sized>(&self, topic: &Q)`
    *   `pub fn recv(&self) -> RecvFuture<'_, (K, T)>`: Returns a future that waits for a message.
    *   `pub fn try_recv(&self) -> Result<(K, T), TryRecvError>`
    *   `pub fn close(&self) -> Result<(), CloseError>`
    *   `pub fn is_closed(&self) -> bool`
    *   `pub fn capacity(&self) -> usize`: Returns the capacity of this receiver's mailbox.
    *   `pub fn is_empty(&self) -> bool`: Returns `true` if this receiver's mailbox is empty.
    *   `pub fn to_sync(self) -> TopicReceiver<K, T>`