Skip to content

Commit 0929b09

Browse files
committed
feat(local): add connect_pair() public API
Mirror asio::local::connect_pair as a free function in boost::corosio. POSIX uses socketpair(); Windows performs a private bind/listen/accept on the caller thread paired with a connect on a short-lived worker thread, so the caller's io_context is never driven. Returns std::error_code (noexcept). Stream and POSIX-only datagram overloads. native_local_stream_socket<Backend> slices to the base parameter; assign() routes through the backend service. Replaces the test-only make_local_*_pair helpers from 4b952ec; tests, benchmarks, and the user guide are migrated.
1 parent 4b952ec commit 0929b09

12 files changed

Lines changed: 670 additions & 313 deletions

‎doc/modules/ROOT/pages/4.guide/4p.unix-sockets.adoc‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Code snippets assume:
2222
#include <boost/corosio/local_stream_socket.hpp>
2323
#include <boost/corosio/local_stream_acceptor.hpp>
2424
#include <boost/corosio/local_datagram_socket.hpp>
25-
#include <boost/corosio/local_socket_pair.hpp>
25+
#include <boost/corosio/local_connect_pair.hpp>
2626
#include <boost/corosio/local_endpoint.hpp>
2727
#include <boost/capy/buffers.hpp>
2828
@@ -123,11 +123,15 @@ capy::task<> client(corosio::io_context& ioc)
123123
=== Socket Pairs
124124

125125
For bidirectional IPC between a parent and child (or two coroutines),
126-
use `make_local_stream_pair()` which calls the `socketpair()` system call:
126+
use `connect_pair()`. On POSIX it uses a single `socketpair()` syscall;
127+
on Windows it performs a private bind/listen/accept/connect rendezvous
128+
on a worker thread.
127129

128130
[source,cpp]
129131
----
130-
auto [s1, s2] = corosio::make_local_stream_pair(ioc);
132+
corosio::local_stream_socket s1(ioc), s2(ioc);
133+
if (auto ec = corosio::connect_pair(s1, s2))
134+
throw std::system_error(ec, "connect_pair");
131135
132136
// Data written to s1 can be read from s2, and vice versa.
133137
co_await s1.write_some(capy::const_buffer("ping", 4));
@@ -138,9 +142,6 @@ auto [ec, n] = co_await s2.read_some(
138142
// buf contains "ping"
139143
----
140144

141-
This is the fastest way to create a connected pair — it uses a single
142-
`socketpair()` syscall with no filesystem paths involved.
143-
144145
== Datagram Sockets
145146

146147
Datagram sockets preserve message boundaries. Each `send` delivers exactly
@@ -173,7 +174,9 @@ After calling `connect()`, use `send`/`recv` without specifying the peer:
173174

174175
[source,cpp]
175176
----
176-
auto [s1, s2] = corosio::make_local_datagram_pair(ioc);
177+
corosio::local_datagram_socket s1(ioc), s2(ioc);
178+
if (auto ec = corosio::connect_pair(s1, s2))
179+
throw std::system_error(ec, "connect_pair");
177180
178181
co_await s1.send(capy::const_buffer("msg", 3));
179182

‎include/boost/corosio.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <boost/corosio/timer.hpp>
3232
#include <boost/corosio/udp_socket.hpp>
3333

34+
#include <boost/corosio/local_connect_pair.hpp>
3435
#include <boost/corosio/local_endpoint.hpp>
3536
#include <boost/corosio/local_stream.hpp>
3637
#include <boost/corosio/local_stream_socket.hpp>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//
2+
// Copyright (c) 2026 Steve Gerbino
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/cppalliance/corosio
8+
//
9+
10+
#ifndef BOOST_COROSIO_LOCAL_CONNECT_PAIR_HPP
11+
#define BOOST_COROSIO_LOCAL_CONNECT_PAIR_HPP
12+
13+
#include <boost/corosio/detail/config.hpp>
14+
#include <boost/corosio/detail/platform.hpp>
15+
#include <boost/corosio/local_stream_socket.hpp>
16+
17+
#if BOOST_COROSIO_POSIX
18+
#include <boost/corosio/local_datagram_socket.hpp>
19+
#endif
20+
21+
#include <system_error>
22+
23+
namespace boost::corosio {
24+
25+
/** Synchronously connect two AF_UNIX stream sockets as a connected pair.
26+
27+
On POSIX the implementation uses `socketpair(AF_UNIX, SOCK_STREAM)`
28+
and adopts the descriptors via `assign()`. On Windows it performs a
29+
private bind/listen/accept on the calling thread paired with a
30+
`connect()` on a short-lived worker thread; the caller's
31+
`io_context` is never driven, so it may be running on another
32+
thread.
33+
34+
Either socket may be a `native_local_stream_socket<Backend>`; the
35+
base reference selects the backend's `assign_socket` through normal
36+
virtual dispatch.
37+
38+
@par Preconditions
39+
Both sockets must be in the closed state.
40+
41+
@par Exception Safety
42+
Nothrow. On failure both sockets remain closed and any underlying
43+
resources are released.
44+
45+
@param a Receives the accepted/first endpoint of the pair.
46+
@param b Receives the connected/second endpoint of the pair.
47+
48+
@return Empty on success; otherwise the underlying system error.
49+
*/
50+
BOOST_COROSIO_DECL
51+
std::error_code
52+
connect_pair(local_stream_socket& a, local_stream_socket& b) noexcept;
53+
54+
#if BOOST_COROSIO_POSIX
55+
56+
/** Synchronously connect two AF_UNIX datagram sockets as a connected pair.
57+
58+
POSIX only. Uses `socketpair(AF_UNIX, SOCK_DGRAM)` and adopts the
59+
descriptors via `assign()`.
60+
61+
@par Preconditions
62+
Both sockets must be in the closed state.
63+
64+
@par Exception Safety
65+
Nothrow.
66+
67+
@param a First socket of the pair.
68+
@param b Second socket of the pair.
69+
70+
@return Empty on success; otherwise the underlying system error.
71+
*/
72+
BOOST_COROSIO_DECL
73+
std::error_code
74+
connect_pair(local_datagram_socket& a, local_datagram_socket& b) noexcept;
75+
76+
#endif // BOOST_COROSIO_POSIX
77+
78+
} // namespace boost::corosio
79+
80+
#endif

‎include/boost/corosio/local_stream_socket.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ class BOOST_COROSIO_DECL local_stream_socket : public io_stream
470470
471471
The socket must not already be open. The fd is adopted
472472
and registered with the platform reactor. Used by
473-
make_local_stream_pair() to wrap socketpair() fds.
473+
connect_pair() to wrap socketpair() fds.
474474
475475
@param fd The file descriptor to adopt. Must be a valid,
476476
open, non-blocking Unix stream socket.

‎include/boost/corosio/test/local_socket_pair.hpp‎

Lines changed: 0 additions & 233 deletions
This file was deleted.

0 commit comments

Comments
 (0)