Spsc class final
SPSC (Single-Producer Single-Consumer) channels - Efficient direct communication.
A high-performance channel type in cross_channel. Optimized for scenarios where exactly one producer communicates with exactly one consumer. Uses efficient algorithms and data structures to minimize overhead.
Performance Characteristics
- Good performance: Efficient message passing, typically ~550-570ns per operation (see benchmarks)
- Minimal allocations: Optimized to reduce garbage collection pressure
- Efficient design: Designed to avoid contention in the hot path
- Ring buffer: Uses power-of-two sized SRSW (Single-Reader Single-Writer) ring buffer
When to Use SPSC
- Performance-sensitive producer-consumer scenarios
- Data streaming between two components
- Game logic (e.g., main thread ↔ render thread communication)
- Sensor data processing
- Any scenario requiring efficient 1:1 communication
Constraints
EXACTLY one producer and one consumer required
- Violation leads to undefined behavior and potential data corruption
- Use XChannel.mpsc for multiple producers
- Use XChannel.mpmc for multiple producers and consumers
Usage Patterns
High-frequency data streaming:
// Audio processing pipeline
final (tx, rx) = Spsc.channel<AudioSample>(capacity: 4096);
// Producer (audio thread)
void audioCallback(AudioSample sample) {
final result = tx.trySend(sample);
if (result is SendErrorFull) {
// Buffer overrun - critical!
handleBufferOverrun();
}
}
// Consumer (processing thread)
await for (final sample in rx.stream()) {
processAudioSample(sample);
}
Game engine messaging:
// Main thread → Render thread
final (renderCommands, renderRx) = Spsc.channel<RenderCommand>(capacity: 1024);
// Main thread
void updateGame() {
final cmd = RenderCommand.drawSprite(sprite, position);
await renderCommands.send(cmd);
}
// Render thread
while (engine.running) {
switch (await renderRx.recv()) {
case RecvOk(value: final cmd):
executeRenderCommand(cmd);
case RecvErrorDisconnected():
break; // Shutdown
}
}
IoT sensor pipeline:
// Sensor → Processing
final (sensorTx, sensorRx) = Spsc.channel<SensorReading>(capacity: 2048);
// High-frequency sensor (producer)
Timer.periodic(Duration(microseconds: 100), (timer) {
final reading = SensorReading.now();
sensorTx.trySend(reading); // Non-blocking
});
// Batch processor (consumer)
final batch = <SensorReading>[];
await for (final reading in sensorRx.stream()) {
batch.add(reading);
if (batch.length >= 100) {
await processBatch(batch);
batch.clear();
}
}
Constructors
- Spsc.new()
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Methods
-
channel<
T> (int capacity, {String? metricsId}) → (SpscSender< T> , SpscReceiver<T> ) - Creates an SPSC channel with the specified buffer capacity.