include/boost/corosio/local_stream_acceptor.hpp

100.0% Lines (85 / 85) 100.0% Functions (21 / 21)
local_stream_acceptor.hpp
f(x) Functions (21)
Function Calls Lines Blocks
boost::corosio::local_stream_acceptor::wait_awaitable::wait_awaitable(boost::corosio::local_stream_acceptor&, boost::corosio::wait_type) :76 8x 100.0% 100.0% boost::corosio::local_stream_acceptor::wait_awaitable::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :88 6x 100.0% 80.0% boost::corosio::local_stream_acceptor::move_accept_awaitable::move_accept_awaitable(boost::corosio::local_stream_acceptor&) :103 6x 100.0% 100.0% boost::corosio::local_stream_acceptor::move_accept_awaitable::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :109 4x 100.0% 80.0% boost::corosio::local_stream_acceptor::move_accept_awaitable::await_resume() const :117 6x 100.0% 100.0% boost::corosio::local_stream_acceptor::accept_awaitable::accept_awaitable(boost::corosio::local_stream_acceptor&, boost::corosio::local_stream_socket&) :138 29x 100.0% 100.0% boost::corosio::local_stream_acceptor::accept_awaitable::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :146 25x 100.0% 80.0% boost::corosio::local_stream_acceptor::accept_awaitable::await_resume() const :153 27x 100.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::corosio::local_stream_acceptor&&) :235 2x 100.0% 100.0% boost::corosio::local_stream_acceptor::is_open() const :319 491x 100.0% 100.0% boost::corosio::local_stream_acceptor::accept(boost::corosio::local_stream_socket&) :341 29x 100.0% 100.0% boost::corosio::local_stream_acceptor::wait(boost::corosio::wait_type) :371 8x 100.0% 100.0% boost::corosio::local_stream_acceptor::accept() :396 6x 100.0% 100.0% void boost::corosio::local_stream_acceptor::set_option<boost::corosio::socket_option::no_delay>(boost::corosio::socket_option::no_delay const&) :493 2x 66.7% 78.0% void boost::corosio::local_stream_acceptor::set_option<boost::corosio::socket_option::reuse_address>(boost::corosio::socket_option::reuse_address const&) :493 4x 88.9% 94.0% boost::corosio::socket_option::no_delay boost::corosio::local_stream_acceptor::get_option<boost::corosio::socket_option::no_delay>() const :520 2x 66.7% 70.0% boost::corosio::socket_option::reuse_address boost::corosio::local_stream_acceptor::get_option<boost::corosio::socket_option::reuse_address>() const :520 4x 91.7% 95.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::corosio::io_object::handle, boost::capy::execution_context&) :643 18x 100.0% 100.0% boost::corosio::local_stream_acceptor::local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_stream_acceptor&&) :655 2x 100.0% 100.0% boost::corosio::local_stream_acceptor::reset_peer_impl(boost::corosio::local_stream_socket&, boost::corosio::io_object::implementation*) :672 8x 100.0% 100.0% boost::corosio::local_stream_acceptor::get() const :682 574x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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_STREAM_ACCEPTOR_HPP
11 #define BOOST_COROSIO_LOCAL_STREAM_ACCEPTOR_HPP
12
13 #include <boost/corosio/family.hpp>
14 #include <boost/corosio/detail/config.hpp>
15 #include <boost/corosio/detail/except.hpp>
16 #include <boost/corosio/detail/op_base.hpp>
17 #include <boost/corosio/wait_type.hpp>
18 #include <boost/corosio/io/io_object.hpp>
19 #include <boost/capy/io_result.hpp>
20 #include <boost/corosio/local_endpoint.hpp>
21 #include <boost/corosio/local_stream_socket.hpp>
22 #include <boost/capy/ex/executor_ref.hpp>
23 #include <boost/capy/ex/execution_context.hpp>
24 #include <boost/capy/ex/io_env.hpp>
25 #include <boost/capy/concept/executor.hpp>
26
27 #include <system_error>
28
29 #include <cassert>
30 #include <concepts>
31 #include <coroutine>
32 #include <cstddef>
33 #include <stop_token>
34 #include <type_traits>
35
36 namespace boost::corosio {
37
38 /** Controls whether @ref local_stream_acceptor::bind() unlinks
39 an existing socket path before binding.
40 */
41 enum class bind_option
42 {
43 /// Bind without touching the socket path.
44 none,
45 /// Unlink the socket path before binding (ignored for abstract paths).
46 unlink_existing
47 };
48
49 /** Accepts inbound Unix domain stream connections, from a coroutine.
50
51 This class provides asynchronous Unix domain stream accept
52 operations that return awaitable types. The acceptor binds
53 to a local endpoint (filesystem path or abstract name) and
54 listens for incoming connections.
55
56 The library does NOT automatically unlink the socket path
57 on close. Callers are responsible for removing the socket
58 file before bind (via @ref bind_option::unlink_existing) or
59 after close.
60
61 @par Thread Safety
62 Distinct objects: Safe.@n
63 Shared objects: Unsafe. An acceptor must not have concurrent
64 accept operations.
65
66 @par Example
67 @par !example bind_listen_accept
68 */
69 class BOOST_COROSIO_DECL local_stream_acceptor : public io_object
70 {
71 struct wait_awaitable : detail::void_op_base<wait_awaitable>
72 {
73 private:
74 friend local_stream_acceptor;
75
76 8x wait_awaitable(local_stream_acceptor& acc, wait_type w) noexcept
77 16x : acc_(acc)
78 8x , w_(w)
79 {
80 8x }
81
82 friend detail::void_op_base<wait_awaitable>;
83
84 local_stream_acceptor& acc_;
85 wait_type w_;
86
87 std::coroutine_handle<>
88 6x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
89 {
90 6x return acc_.get().wait(h, ex, w_, token_, &ec_);
91 }
92 };
93
94 struct move_accept_awaitable : detail::void_op_base<move_accept_awaitable>
95 {
96 private:
97 friend local_stream_acceptor;
98 friend detail::void_op_base<move_accept_awaitable>;
99
100 local_stream_acceptor& acc_;
101 mutable io_object::implementation* peer_impl_ = nullptr;
102
103 6x explicit move_accept_awaitable(local_stream_acceptor& acc) noexcept
104 6x : acc_(acc)
105 {
106 6x }
107
108 std::coroutine_handle<>
109 4x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
110 {
111 12x return acc_.get().accept(
112 12x h, ex, this->token_, &this->ec_, &peer_impl_);
113 }
114
115 public:
116 [[nodiscard]] capy::io_result<local_stream_socket>
117 6x await_resume() const noexcept
118 {
119 6x if (this->ec_ || !peer_impl_)
120 4x return {this->ec_, local_stream_socket()};
121
122 2x local_stream_socket peer(acc_.ctx_);
123 2x reset_peer_impl(peer, peer_impl_);
124 2x return {this->ec_, std::move(peer)};
125 2x }
126 };
127
128 struct accept_awaitable : detail::void_op_base<accept_awaitable>
129 {
130 private:
131 friend local_stream_acceptor;
132 friend detail::void_op_base<accept_awaitable>;
133
134 local_stream_acceptor& acc_;
135 local_stream_socket& peer_;
136 mutable io_object::implementation* peer_impl_ = nullptr;
137
138 29x accept_awaitable(
139 local_stream_acceptor& acc, local_stream_socket& peer) noexcept
140 58x : acc_(acc)
141 29x , peer_(peer)
142 {
143 29x }
144
145 std::coroutine_handle<>
146 25x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
147 {
148 75x return acc_.get().accept(
149 75x h, ex, this->token_, &this->ec_, &peer_impl_);
150 }
151
152 public:
153 27x [[nodiscard]] capy::io_result<> await_resume() const noexcept
154 {
155 27x if (!this->ec_ && peer_impl_)
156 17x peer_.h_.reset(peer_impl_);
157 27x return {this->ec_};
158 }
159 };
160
161 public:
162 /** Closes the acceptor if open, cancelling any pending operations.
163 */
164 ~local_stream_acceptor() override;
165
166 /** Construct an acceptor from an execution context.
167
168 @param ctx The execution context that owns this acceptor.
169 */
170 explicit local_stream_acceptor(capy::execution_context& ctx);
171
172 /** Convenience constructor: open + bind + listen.
173
174 Creates a fully-bound listening acceptor in a single
175 expression, throwing the codes the piecewise `open()` +
176 `bind()` + `listen()` path returns.
177
178 @param ctx The execution context that owns this acceptor.
179 @param ep The local endpoint to bind to.
180 @param backlog The maximum pending connection queue length.
181
182 @throws std::system_error on open, bind, or listen failure.
183 */
184 local_stream_acceptor(
185 capy::execution_context& ctx,
186 corosio::local_endpoint ep,
187 int backlog = 128);
188
189 /** Construct an acceptor from an executor.
190
191 The acceptor is associated with the executor's context.
192
193 @param ex The executor whose context owns the acceptor.
194
195 @tparam Ex A type satisfying @ref capy::Executor. Must not
196 be `local_stream_acceptor` itself (disables implicit
197 conversion from move).
198 */
199 template<class Ex>
200 requires(!std::
201 same_as<std::remove_cvref_t<Ex>, local_stream_acceptor>) &&
202 capy::Executor<Ex>
203 explicit local_stream_acceptor(Ex const& ex)
204 : local_stream_acceptor(ex.context())
205 {
206 }
207
208 /** Convenience constructor from an executor.
209
210 @param ex The executor whose context owns the acceptor.
211 @param ep The local endpoint to bind to.
212 @param backlog The maximum pending connection queue length.
213
214 @tparam Ex A type satisfying @ref capy::Executor.
215
216 @throws std::system_error on open, bind, or listen failure.
217 */
218 template<class Ex>
219 requires capy::Executor<Ex>
220 local_stream_acceptor(
221 Ex const& ex, corosio::local_endpoint ep, int backlog = 128)
222 : local_stream_acceptor(ex.context(), std::move(ep), backlog)
223 {
224 }
225
226 /** Transfers ownership of the acceptor resources from another
227 acceptor.
228
229 @param other The acceptor to move from.
230
231 @pre No awaitables returned by @p other's methods exist.
232 @pre The execution context associated with @p other must
233 outlive this acceptor.
234 */
235 2x local_stream_acceptor(local_stream_acceptor&& other) noexcept
236 2x : local_stream_acceptor(other.ctx_, std::move(other))
237 {
238 2x }
239
240 /** Closes any existing acceptor and transfers ownership from
241 another acceptor. Both acceptors must share the same
242 execution context.
243
244 @param other The acceptor to move from.
245
246 @return Reference to this acceptor.
247
248 @pre `&ctx_ == &other.ctx_` (same execution context).
249 @pre No awaitables returned by either `*this` or @p other's
250 methods exist.
251 */
252 local_stream_acceptor& operator=(local_stream_acceptor&& other) noexcept
253 {
254 assert(
255 &ctx_ == &other.ctx_ &&
256 "move-assign requires the same execution_context");
257 if (this != &other)
258 {
259 close();
260 io_object::operator=(std::move(other));
261 }
262 return *this;
263 }
264
265 /// Copy construction is disabled; the handle is uniquely owned.
266 local_stream_acceptor(local_stream_acceptor const&) = delete;
267 /// Copy assignment is disabled; the handle is uniquely owned.
268 local_stream_acceptor& operator=(local_stream_acceptor const&) = delete;
269
270 /** Create the acceptor socket.
271
272 Failures such as descriptor exhaustion are normal runtime
273 conditions and are reported through the returned error code.
274
275
276 @return The error code, empty on success.
277 */
278 [[nodiscard]] std::error_code open() noexcept;
279
280 /** Bind to a local endpoint.
281
282 @param ep The local endpoint (path) to bind to.
283 @param opt Bind options. Pass bind_option::unlink_existing
284 to unlink the socket path before binding (ignored for
285 abstract sockets and empty endpoints).
286
287 @return An error code on failure, empty on success.
288
289 A closed acceptor reports `errc::bad_file_descriptor`.
290 */
291 [[nodiscard]] std::error_code bind(
292 corosio::local_endpoint ep,
293 bind_option opt = bind_option::none) noexcept;
294
295 /** Start listening for incoming connections.
296
297 @param backlog The maximum pending connection queue length.
298
299 @return An error code on failure, empty on success.
300
301 A closed acceptor reports `errc::bad_file_descriptor`.
302 */
303 [[nodiscard]] std::error_code listen(int backlog = 128) noexcept;
304
305 /** Close the acceptor.
306
307 Cancels any pending accept operations and releases the
308 underlying socket. Has no effect if the acceptor is not
309 open.
310
311 @post is_open() == false
312 */
313 void close() noexcept;
314
315 /** Check if the acceptor has an open socket handle.
316
317 @return `true` if the acceptor holds an open handle.
318 */
319 491x bool is_open() const noexcept
320 {
321 491x return h_ && get().is_open();
322 }
323
324 /** Initiate an asynchronous accept into an existing socket.
325
326 Completes when a new connection is available. On success
327 @p peer is reset to the accepted connection. Only one
328 accept may be in flight at a time.
329
330 @param peer The socket to receive the accepted connection.
331
332 @par Cancellation
333 Supports cancellation via stop_token or cancel().
334 On cancellation, yields `capy::cond::canceled` and
335 @p peer is not modified.
336
337 @return An awaitable that completes with io_result<>.
338
339 A closed acceptor reports `errc::bad_file_descriptor`.
340 */
341 29x [[nodiscard]] auto accept(local_stream_socket& peer)
342 {
343 29x accept_awaitable aw(*this, peer);
344 29x if (!is_open())
345 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
346 29x return aw;
347 }
348
349 /** Wait for an incoming connection or readiness condition.
350
351 Suspends until the listen socket is ready in the
352 requested direction. For `wait_type::read`, completion
353 signals that a subsequent @ref accept succeeds
354 without blocking. A connection already queued when the
355 wait begins completes it immediately. No connection is
356 consumed.
357
358 @note `wait_type::write` is not usable on an acceptor:
359 writability carries no meaning for a listening socket, so
360 the wait fails with `errc::operation_not_supported` on
361 every backend.
362
363 @param w The wait direction.
364
365 @return An awaitable that completes with `io_result<>`.
366
367 A closed acceptor completes with `errc::bad_file_descriptor`.
368
369 @pre This acceptor must outlive the returned awaitable.
370 */
371 8x [[nodiscard]] auto wait(wait_type w)
372 {
373 8x wait_awaitable aw(*this, w);
374 8x if (!is_open())
375 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
376 8x return aw;
377 }
378
379 /** Initiate an asynchronous accept, returning the socket.
380
381 Completes when a new connection is available. Only one
382 accept may be in flight at a time.
383
384 @par Cancellation
385 Supports cancellation via stop_token or cancel().
386 On cancellation, yields `capy::cond::canceled` with
387 a default-constructed socket.
388
389 @return An awaitable that completes with
390 io_result<`local_stream_socket`>.
391
392 A closed acceptor reports `errc::bad_file_descriptor`.
393 On failure the returned socket is default-constructed and
394 may only be destroyed or assigned.
395 */
396 6x [[nodiscard]] auto accept()
397 {
398 6x move_accept_awaitable aw(*this);
399 6x if (!is_open())
400 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
401 6x return aw;
402 }
403
404 /** Cancel pending asynchronous accept operations.
405
406 Outstanding accept operations complete with
407 @c capy::cond::canceled. Safe to call when no
408 operations are pending (no-op).
409 */
410 void cancel() noexcept;
411
412 /** Release ownership of the native socket handle.
413
414 Deregisters the acceptor from the reactor and cancels
415 pending operations without closing the descriptor. The
416 caller takes ownership of the returned handle.
417
418 @return The native handle.
419
420 @throws std::system_error `errc::bad_file_descriptor` if the
421 acceptor is not open.
422
423 @post is_open() == false
424 */
425 native_handle_type release();
426
427 /** Get the native socket handle.
428
429 @return The native socket handle, or -1/INVALID_SOCKET if not
430 open.
431
432 @pre None. May be called on closed acceptors.
433 */
434 native_handle_type native_handle() const noexcept;
435
436 /** Assign an existing native socket to this acceptor.
437
438 Adopts a listening socket created outside the library —
439 received from a service manager, inherited, or made natively —
440 and registers it with the backend. The socket must be a
441 listening stream socket in the local IPC family. Adoption
442 never alters the descriptor's flags or options: on POSIX the
443 fd must already be non-blocking, and on Windows the socket
444 must be overlapped-capable.
445
446 Adoption does not verify listen state; @ref accept reports the
447 error if the socket is not listening.
448
449 If this object is already open, pending operations complete
450 with `errc::operation_canceled` and the held socket is closed
451 before the new one is adopted.
452
453 @par Exception Safety
454 Strong guarantee on validation failure: the object is
455 unchanged. If backend registration fails, the object either
456 retains its previous socket or is left closed, depending on
457 the backend. In all failure cases the caller retains
458 ownership of `fd`.
459
460 @param fd The native socket to adopt. On success the object
461 owns it and closes it.
462
463 @return The error code, empty on success. Validation and
464 registration failures are normal runtime conditions when
465 adopting foreign descriptors.
466 */
467 [[nodiscard]] std::error_code assign(native_handle_type fd) noexcept;
468
469 /** Return the local endpoint the acceptor is bound to.
470
471 Safe to call in any state.
472
473 @return The bound local endpoint, or a default-constructed
474 endpoint if the acceptor is not open or not yet bound.
475 */
476 corosio::local_endpoint local_endpoint() const noexcept;
477
478 /** Set a socket option on the acceptor.
479
480 Applies a type-safe socket option to the underlying socket.
481 The option type encodes the protocol level and option name.
482
483 @param opt The option to set.
484
485 @tparam Option A socket option type providing static
486 `level()` and `name()` members, and `data()` / `size()`
487 accessors.
488
489 @throws std::system_error `errc::bad_file_descriptor` if the
490 acceptor is not open; otherwise thrown on failure.
491 */
492 template<class Option>
493 6x void set_option(Option const& opt)
494 {
495 6x if (!is_open())
496 2x detail::throw_system_error(
497 4x make_error_code(std::errc::bad_file_descriptor),
498 "local_stream_acceptor::set_option");
499 4x auto const fam = get().family();
500 4x std::error_code ec = get().set_option(
501 opt.level(fam), opt.name(fam), opt.data(fam), opt.size(fam));
502 4x if (ec)
503 2x detail::throw_system_error(ec, "local_stream_acceptor::set_option");
504 2x }
505
506 /** Get a socket option from the acceptor.
507
508 Retrieves the current value of a type-safe socket option.
509
510 @return The current option value.
511
512 @tparam Option A socket option type providing static
513 `level()` and `name()` members, and `data()` / `size()`
514 / `resize()` members.
515
516 @throws std::system_error `errc::bad_file_descriptor` if the
517 acceptor is not open; otherwise thrown on failure.
518 */
519 template<class Option>
520 6x Option get_option() const
521 {
522 6x if (!is_open())
523 2x detail::throw_system_error(
524 4x make_error_code(std::errc::bad_file_descriptor),
525 "local_stream_acceptor::get_option");
526 4x Option opt{};
527 4x auto const fam = get().family();
528 4x std::size_t sz = opt.size(fam);
529 std::error_code ec =
530 4x get().get_option(opt.level(fam), opt.name(fam), opt.data(fam), &sz);
531 4x if (ec)
532 2x detail::throw_system_error(ec, "local_stream_acceptor::get_option");
533 2x opt.resize(fam, sz);
534 2x return opt;
535 }
536
537 /** Backends derive from this to implement accept, option, and
538 lifecycle management.
539 */
540 struct implementation : io_object::implementation
541 {
542 /** Initiate an asynchronous accept.
543
544 On completion the backend sets @p *ec and, on
545 success, stores a pointer to the new socket
546 implementation in @p *impl_out.
547
548 @param h Coroutine handle to resume.
549 @param ex Executor for dispatching the completion.
550 @param token Stop token for cancellation.
551 @param ec Output error code.
552 @param impl_out Output pointer for the accepted socket.
553 @return Coroutine handle to resume immediately.
554 */
555 virtual std::coroutine_handle<> accept(
556 std::coroutine_handle<> h,
557 capy::executor_ref ex,
558 std::stop_token token,
559 std::error_code* ec,
560 io_object::implementation** impl_out) = 0;
561
562 /** Initiate an asynchronous wait for acceptor readiness.
563
564 Completes when the listen socket becomes ready for
565 the specified direction. No connection is consumed.
566
567 @param h Coroutine handle to resume on completion.
568 @param ex Executor for dispatching the completion.
569 @param w The direction to wait on.
570 @param token Stop token for cancellation.
571 @param ec Output error code.
572
573 @return Coroutine handle to resume immediately.
574 */
575 virtual std::coroutine_handle<> wait(
576 std::coroutine_handle<> h,
577 capy::executor_ref ex,
578 wait_type w,
579 std::stop_token token,
580 std::error_code* ec) = 0;
581
582 /// Return the cached local endpoint.
583 virtual corosio::local_endpoint local_endpoint() const noexcept = 0;
584
585 /// Return whether the underlying socket is open.
586 virtual bool is_open() const noexcept = 0;
587
588 /// Return the native handle, or the platform sentinel if closed.
589 virtual native_handle_type native_handle() const noexcept = 0;
590
591 /** Return the socket's address family.
592
593 Local sockets have no IP family; implementations return
594 `v4`, which the family-neutral options applicable to them
595 ignore.
596
597 @return The address family for option rendering.
598 */
599 virtual corosio::family family() const noexcept = 0;
600
601 /// Release and return the native handle without closing.
602 virtual native_handle_type release_socket() noexcept = 0;
603
604 /// Cancel pending accept operations.
605 virtual void cancel() noexcept = 0;
606
607 /** Set a raw socket option.
608
609 @param level The protocol level (e.g. `SOL_SOCKET`).
610 @param optname The option name.
611 @param data Pointer to the option value.
612 @param size Size of the option value in bytes.
613
614 @return The error code, empty on success.
615 */
616 virtual std::error_code set_option(
617 int level,
618 int optname,
619 void const* data,
620 std::size_t size) noexcept = 0;
621
622 /** Get a raw socket option.
623
624 @param level The protocol level (e.g. `SOL_SOCKET`).
625 @param optname The option name.
626 @param data Pointer to storage for the option value.
627 @param size In/out size of the storage, in bytes.
628
629 @return The error code, empty on success.
630 */
631 virtual std::error_code
632 get_option(int level, int optname, void* data, std::size_t* size)
633 const noexcept = 0;
634 };
635
636 protected:
637 /** Adopt an existing handle bound to a context.
638
639 @param h The handle the acceptor takes ownership of.
640
641 @param ctx The context the acceptor draws its service from.
642 */
643 18x local_stream_acceptor(handle h, capy::execution_context& ctx) noexcept
644 18x : io_object(std::move(h))
645 18x , ctx_(ctx)
646 {
647 18x }
648
649 /** Move construct, rebinding to a context.
650
651 @param ctx The context the acceptor draws its service from.
652
653 @param other The acceptor to take the handle from.
654 */
655 2x local_stream_acceptor(
656 capy::execution_context& ctx, local_stream_acceptor&& other) noexcept
657 2x : io_object(std::move(other))
658 2x , ctx_(ctx)
659 {
660 2x }
661
662 /** Install an accepted implementation into the peer socket.
663
664 Derived acceptors call this to hand the accepted connection to
665 the caller's socket, which cannot reach @ref io_object::handle
666 itself.
667
668 @param peer The socket receiving the accepted connection.
669
670 @param impl The accepted implementation, or `nullptr` on failure.
671 */
672 8x static void reset_peer_impl(
673 local_stream_socket& peer, io_object::implementation* impl) noexcept
674 {
675 8x if (impl)
676 8x peer.h_.reset(impl);
677 8x }
678
679 private:
680 capy::execution_context& ctx_;
681
682 574x inline implementation& get() const noexcept
683 {
684 574x return *static_cast<implementation*>(h_.get());
685 }
686 };
687
688 } // namespace boost::corosio
689
690 #endif // BOOST_COROSIO_LOCAL_STREAM_ACCEPTOR_HPP
691