Design Rationale
This page explains the key design decisions in Corosio and the trade-offs considered.
Coroutine-First Design
Affine Awaitable Protocol
Decision
Executor affinity propagates through await_suspend parameters rather than
thread-local storage or coroutine promise members.
io_result<T> Type
Decision
Operations return io_result<T> which combines an error code with optional
values and supports both structured bindings and exceptions.
Type-Erased Dispatchers
Inheritance Hierarchy
Decision
socket inherits from io_stream which inherits from io_object.
io_object
├── acceptor
├── resolver
├── timer
├── signal_set
└── io_stream
├── socket
└── wolfssl_stream
Buffer Type Erasure (any_bufref)
consuming_buffers for Composed Operations
Separate open() and connect()
Move-Only I/O Objects
Platform-Specific Backends
WolfSSL for TLS
Summary
Corosio’s design prioritizes:
-
Simplicity: One way to do things, not two
-
Performance: Zero-overhead abstractions where possible
-
Safety: Ownership semantics prevent resource leaks
-
Composability: Works with standard C++ patterns
-
Extensibility: Clean hierarchy for new types
Trade-offs generally favor correctness and clarity over maximum flexibility.