Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |
Launch files
Messages
Services
Plugins
Recent questions tagged wirestead at Robotics Stack Exchange
Package Summary
| Version | 0.9.6 |
| License | Apache-2.0 |
| Build type | CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/wirestead/wirestead.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-20 |
| Dev Status | DEVELOPED |
| Released | UNRELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jinwoo Sung
Authors
Wirestead™
Robust, simple async communication for modern C++20.
Serial · TCP · UDP · UDS — one API for all four, on Linux, macOS and Windows, x64 and arm64.
Description
wirestead provides a unified interface for asynchronous communication across different transports, allowing applications to switch between Serial, TCP, UDP, and UDS with minimal code changes. The public C++ API exposes builders and wrappers for all four transport families.
The project prioritizes API clarity, predictable runtime behavior, and stability over rapid feature expansion.
#include <iostream>
#include <wirestead/wirestead.hpp>
auto client = wirestead::tcp_client("127.0.0.1", 8080)
.max_retries(3)
.on_data([](const wirestead::MessageContext& ctx) {
std::cout << "received " << ctx.data().size() << " bytes\n";
})
.build();
client->start_sync();
client->send("hello");
The same shape builds a serial port, a UDP socket or a UDS endpoint — see Quick Start.
Security note: transports send data in plaintext by default. TCP can do TLS in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON- server and client, with the client verifying the server; UDP, Serial and UDS cannot, and DTLS is not supported. See Security and Threat Model before usingwiresteadover an untrusted network.
How Wirestead compares
Wirestead is a multi-transport async library. Most alternatives are either a single-transport library or a set of ready-to-run ROS nodes, so the useful question is usually which shape you need rather than which has more features.
| Transports | Async | Platforms | Install | |
|---|---|---|---|---|
| Wirestead | Serial, TCP, UDP, UDS | yes, one io_context model across all four |
Linux, macOS, Windows — x64 and arm64 | vcpkg, FetchContent, PyPI |
| transport_drivers | Serial, UDP | yes (standalone Asio) | Linux (ROS 2) | rosdep / apt |
| libserial | Serial | no | Linux only | apt install libserial-dev |
| serialib | Serial | no | Linux, Windows | copy two files |
| Boost.Asio directly | everything | yes | everywhere | you already have it |
Wirestead fits best when one application speaks over more than one transport — a serial sensor, a TCP command server, a UDP telemetry feed — and you would otherwise write reconnect, buffering and framing three times against three different APIs. The four transports share one API, so switching between them is a builder change rather than a rewrite. It runs on Linux, macOS and Windows alike, which the serial-only libraries above do not, and latency is published per release on real hardware: see the benchmark releases. The Feature Highlights below cover what it adds on top of Asio.
When to use something else
-
You only need serial, on Linux.
apt install libserial-devand you are done. Wirestead pulls in Boost and asks you to build it; that is a poor trade for one serial port. - You want the smallest possible dependency. serialib is two files with no dependencies at all.
-
You are on ROS 2 and want a bridge, not a library.
transport_driversshipsserial_bridgeandudp_bridge_node_exe— running executables that move bytes between a device and a topic. Wirestead gives you a library to write your own node against;wirestead_rosprovides a lifecycle shutdown gate,RuntimeStatsreporting ontodiagnostic_updater, and a reference lifecycle driver, but no drop-in bridge node. If a bridge is all you need,transport_driversis less work. - You know Asio well and want direct control. Any wrapper is in your way. Wirestead is a wrapper.
Feature Highlights
- Unified transport surface: Consistent builders and wrappers for TCP client/server, UDP, Serial, and UDS.
- Callback-scoped data views: Avoid unnecessary copies during callbacks, with explicit ownership-copy helpers for stored data. Each payload carries the time it arrived, so a timestamp does not have to be taken after the fact.
-
Message framing: Line-delimited, start/end pattern, and length-prefixed framers, or your own
IFramer. -
Optional TLS: TCP client and server in a build configured with
-DWIRESTEAD_ENABLE_TLS=ON, with the client verifying the server. - Fluent API with CRTP Builders: Type-safe configuration with improved method chaining.
- Built for devices: Serial low-latency mode and RS-485, UDP multicast, a per-channel silence age for spotting a sensor that stopped talking, and a hook for putting the io threads on a real-time policy. See Tuning.
-
Tested runtime behavior: Unit, integration, and end-to-end test suites are part of the repository and documented in
test/.
Requirements
- C++20 compiler: GCC 10+, Clang 14+, or MSVC 2022. CMake enforces these and fails the configure step below them. CI builds GCC on Ubuntu 22.04 and 24.04, Clang on Ubuntu 24.04 and macOS, and MSVC on Windows, each on x64 and arm64.
- CMake 3.12 or later for plain builds; CMake 3.21 or later for the repository presets
- Boost 1.74.0 or later, which covers the system packages on Ubuntu 22.04 (1.74), RHEL 9 (1.75) and Ubuntu 24.04 (1.83). vcpkg remains the recommended dependency supplier; CI builds against the 1.74 floor as well as current Boost.
📦 Installation
vcpkg (recommended)
vcpkg install wirestead
CMake FetchContent
include(FetchContent)
FetchContent_Declare(wirestead
GIT_REPOSITORY https://github.com/wirestead/wirestead.git
GIT_TAG v0.9.6)
FetchContent_MakeAvailable(wirestead)
target_link_libraries(your_target PRIVATE wirestead::wirestead)
Python
pip install wirestead
File truncated at 100 lines see the full file
Changelog
All notable changes to Wirestead are documented in this file.
This project follows the Keep a Changelog section names where practical. The
core C++ API is still pre-1.0; see docs/api_stability.md for compatibility
and ABI policy.
Unreleased
Fixed
-
stop()called from inside a serial callback threw instead of stopping.The callback runs on the transport’s own io thread, and
stop()joined that thread unconditionally, so the call joined the thread with itself:std::system_error, “Resource deadlock avoided”. Without a catch at the call site the library’s callback dispatch swallowed and logged it, which hid the real damage - the throw unwound beforeio_context::restart()and before the wrapper released the channel, so the object was left half-stopped. A laterstop()returned, but a restart’s future never completed.A
stop()from the io thread now requests the shutdown and returns without joining, and a laterstop()from outside completes it, waiting even when a shutdown was already requested. After that call returns the object can be restarted and destroyed. Restarting from inside a callback, before the shutdown completes, remains unsupported.Reproduced in
test/repro/serial_stop_in_callback_repro.cc; covered bySerialStopInCallbackTest, which checks that the callback’sstop()does not throw and that a restarted channel receives data again. -
The CPack Debian package named the wrong Boost package.
It required only
libboost-system-dev. The package ships the headers as well as the shared library, and those headers reachboost/asio, so it also needslibboost-dev.libboost-system-devstays, becausewiresteadConfig.cmakecallsfind_dependency(Boost COMPONENTS system)and that needs the component’s CMake files. These are the same two keyspackage.xmlhas declared since v0.9.6; the CPack side was missed then because only the ROS packaging was in view.A CPack package has never been published, so nothing installed is affected.
Removed
-
Breaking: the Unilink compatibility layer, promised for the v0.9.x line only. This is why the next release is v0.10.0 rather than a v0.9 patch.
Gone:
namespace unilink, the<unilink/...>forwarding headers,find_package(unilink)with itsunilink::unilink,unilink_sharedandunilink_statictargets,unilink.pc, theUNILINK_API/UNILINK_EXPORT/UNILINK_LOG_*macros,UnilinkException, and theUNILINK_*CMake option andUNILINK_LOG_LEVELfallbacks. The first group fails loudly at configure or compile time. The last two do not: an old-DUNILINK_BUILD_TESTS=ONdraws only CMake’s unused-variable warning, andUNILINK_LOG_LEVEL=debugis ignored outright.Migrate on v0.9.x first, where both names build; see
docs/migration-from-unilink.md. For packagers, the install tree no longer containsinclude/unilink/,lib/cmake/unilink/orunilink.pc, so the vcpkg port’svcpkg_cmake_config_fixup(PACKAGE_NAME unilink)must go with this release or the port build fails. -
wirestead/memory/memory_validator.hpp, in full.The header declared eleven free functions in
memory::memory_validator, theMemoryValidatorRAII class and the threeMemoryPatternGeneratorstatics. None of them had a definition anywhere - there is nomemory_validator.ccand never was - sonmfinds no matching symbol in any library this project has ever built, shared or static. Nothing included the header either, not evenwirestead.hpp, yet it was listed inWiresteadSources.cmakeand so installed into the consumer’s include directory.Nothing can break, because nothing could ever have linked against it. Most of the API was also unimplementable as declared:
memory_accessible()cannot be answered portably for an arbitrary pointer, anddouble_free()/use_after_free()take a raw pointer with no allocator context. The parts that were implementable already exist asbase::safe_memory::safe_memcpyand are used by five transports, and the real checking is done by the ASan/UBSan Memory Safety Tests job. -
ThreadSafeState,ThreadSafeCounter,ThreadSafeFlagand theThreadSafeLinkStatealias, fromwirestead/concurrency/thread_safe_state.hpp.This is a breaking change. These are templates and inline functions, so an external consumer could have been using them successfully; nothing inside this project was. There were no instantiations in the library, the tests, or any of the six satellite repositories.
AtomicStateand itsAtomicLinkStatealias stay, and the header stays with them: that alias is the state primitive every transport actually uses. It is what made the three removed classes look load-bearing from a distance and they are not -ThreadSafeStatewas only ever reachable throughThreadSafeLinkState, which nothing named.Adopting rather than deleting was considered and rejected.
ThreadSafeState::notify_callbacks()took a mutex on every state transition to iterate a callback list nothing ever registered into, so converting the transports to it would have added a lock per connection state change and bought
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| wirestead_ros |