OneShot class
One-shot channels - Promise-like single-value delivery with advanced semantics.
Specialized channels for delivering exactly one value, similar to futures but with more flexible consumption patterns. Perfect for request-response scenarios, async initialization, and promise-like patterns.
Core Features
- Single-value semantics: Exactly one value can be sent
- Flexible consumption: Choose between consume-once or multi-reader patterns
- Promise-like behavior: Similar to futures but with channel semantics
- Type-safe results: Explicit success/failure handling
- Zero buffering: Direct producer-to-consumer handoff
Consumption Modes
consumeOnce: true
(Default Promise Behavior)
- First receiver gets the value and consumes it
- Channel disconnects immediately after consumption
- Subsequent receivers get
RecvErrorDisconnected
- Perfect for request-response patterns
consumeOnce: false
(Broadcast Promise)
- All receivers (current and future) get the same value
- Value remains available until explicitly handled
- Multiple receivers can read the same result
- Perfect for initialization values or shared results
When to Use OneShot
- Request-response patterns: Client sends request, waits for single response
- Async initialization: Wait for setup completion across multiple components
- Result broadcasting: Share a computed result with multiple consumers
- Promise coordination: Advanced promise-like patterns with explicit control
- Resource resolution: Resolve a resource once, use many times
- Configuration loading: Load config once, access from multiple places
Performance Characteristics
- Lightweight: Minimal memory footprint (single value storage)
- Efficient delivery: Direct value handoff for single-value scenarios
- Good performance: ~381-390ns per operation (see benchmarks)
- Simple storage: Single memory location for value storage
Usage Patterns
Request-response (consumeOnce: true):
// Client-server request pattern
Future<ApiResponse> makeRequest(ApiRequest request) async {
final (responseTx, responseRx) = OneShot.channel<ApiResponse>(consumeOnce: true);
// Send request with response channel
await requestChannel.send(RequestWithResponse(request, responseTx));
// Wait for single response
final result = await responseRx.recv();
return switch (result) {
RecvOk(value: final response) => response,
RecvErrorDisconnected() => throw TimeoutException('Server disconnected'),
_ => throw StateError('Unexpected result: $result'),
};
}
// Server side
await for (final requestWithResponse in requestChannel.stream()) {
final response = await processRequest(requestWithResponse.request);
await requestWithResponse.responseTx.send(response); // Consumed by one client
}
Shared initialization (consumeOnce: false):
// Global configuration initialization
class ConfigManager {
static final (configTx, configRx) = OneShot.channel<AppConfig>(consumeOnce: false);
static bool _initialized = false;
static Future<void> initialize() async {
if (_initialized) return;
_initialized = true;
final config = await loadConfigFromServer();
await configTx.send(config); // Available to all readers
}
static Future<AppConfig> getConfig() async {
final result = await configRx.recv();
return result.valueOrNull!; // Same config for all callers
}
}
// Multiple components can access the same config
final userConfig = await ConfigManager.getConfig();
final dbConfig = await ConfigManager.getConfig(); // Same instance
Resource resolution pattern:
// Database connection pool initialization
class DatabasePool {
final (poolTx, poolRx) = OneShot.channel<ConnectionPool>(consumeOnce: false);
Future<void> initializePool() async {
final pool = await ConnectionPool.create(
maxConnections: 10,
connectionString: connectionString,
);
await poolTx.send(pool); // Available to all consumers
}
Future<Connection> getConnection() async {
final result = await poolRx.recv();
final pool = result.valueOrNull!;
return await pool.getConnection();
}
}
Advanced promise coordination:
// Coordinated async operations
class AsyncOperationCoordinator {
final operations = <String, OneShot>{};
(OneShotSender<T>, OneShotReceiver<T>) createOperation<T>(String name, {bool shared = false}) {
final (tx, rx) = OneShot.channel<T>(consumeOnce: !shared);
operations[name] = (tx, rx);
return (tx, rx);
}
Future<T> waitForOperation<T>(String name) async {
final (_, rx) = operations[name] as (OneShotSender<T>, OneShotReceiver<T>);
final result = await rx.recv();
return result.valueOrNull!;
}
}
Constructors
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> ({bool consumeOnce = false, String? metricsId}) → (OneShotSender< T> , OneShotReceiver<T> ) - Creates a one-shot channel for single-value delivery.