TLA Line data Source code
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_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_SERVICE_HPP
11 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_SERVICE_HPP
12 :
13 : #include <boost/corosio/io/io_object.hpp>
14 : #include <boost/corosio/detail/scheduler_op.hpp>
15 : #include <boost/corosio/native/detail/reactor/reactor_service_state.hpp>
16 : #include <boost/capy/ex/execution_context.hpp>
17 :
18 : #include <memory>
19 : #include <mutex>
20 :
21 : namespace boost::corosio::detail {
22 :
23 : /** CRTP base for reactor-backed socket/datagram service implementations.
24 :
25 : Provides the shared construct/destroy/shutdown/close/post/work
26 : logic that is identical across all reactor backends and socket
27 : types. Derived classes add only protocol-specific open/bind.
28 :
29 : @tparam Derived The concrete service type (CRTP).
30 : @tparam ServiceBase The abstract service base (tcp_service
31 : or udp_service).
32 : @tparam Scheduler The backend's scheduler type.
33 : @tparam Impl The backend's socket/datagram impl type.
34 : */
35 : template<class Derived, class ServiceBase, class Scheduler, class Impl>
36 : class reactor_socket_service : public ServiceBase
37 : {
38 : friend Derived;
39 : using state_type = reactor_service_state<Scheduler, Impl>;
40 :
41 : protected:
42 : // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
43 HIT 2340 : explicit reactor_socket_service(capy::execution_context& ctx)
44 2340 : : state_(
45 : std::make_unique<state_type>(
46 2340 : ctx.template use_service<Scheduler>()))
47 : {
48 2340 : }
49 :
50 : public:
51 2340 : ~reactor_socket_service() override = default;
52 :
53 2340 : void shutdown() override
54 : {
55 2340 : std::lock_guard lock(state_->mutex_);
56 :
57 2340 : while (auto* impl = state_->impl_list_.pop_front())
58 : {
59 MIS 0 : static_cast<Derived*>(this)->pre_shutdown(impl);
60 0 : impl->close_socket();
61 : }
62 :
63 : // Don't clear impl_ptrs_ here. The scheduler shuts down after us
64 : // and drains completed_ops_, calling destroy() on each queued op.
65 : // Letting ~state_ release the ptrs (during service destruction,
66 : // after scheduler shutdown) keeps every impl alive until all ops
67 : // have been drained.
68 HIT 2340 : }
69 :
70 22309 : io_object::implementation* construct() override
71 : {
72 22309 : auto impl = std::make_shared<Impl>(static_cast<Derived&>(*this));
73 22309 : auto* raw = impl.get();
74 :
75 : {
76 22309 : std::lock_guard lock(state_->mutex_);
77 22309 : state_->impl_ptrs_.emplace(raw, std::move(impl));
78 22309 : state_->impl_list_.push_back(raw);
79 22309 : }
80 :
81 22309 : return raw;
82 22309 : }
83 :
84 22309 : void destroy(io_object::implementation* impl) override
85 : {
86 22309 : auto* typed = static_cast<Impl*>(impl);
87 22309 : static_cast<Derived*>(this)->pre_destroy(typed);
88 22309 : typed->close_socket();
89 22309 : std::lock_guard lock(state_->mutex_);
90 22309 : state_->impl_list_.remove(typed);
91 22309 : state_->impl_ptrs_.erase(typed);
92 22309 : }
93 :
94 37194 : void close(io_object::handle& h) override
95 : {
96 37194 : static_cast<Impl*>(h.get())->close_socket();
97 37194 : }
98 :
99 467087 : Scheduler& scheduler() const noexcept
100 : {
101 467087 : return state_->sched_;
102 : }
103 :
104 87137 : void post(scheduler_op* op)
105 : {
106 87137 : state_->sched_.post(op);
107 87137 : }
108 :
109 7755 : void work_started() noexcept
110 : {
111 7755 : state_->sched_.work_started();
112 7755 : }
113 :
114 299 : void work_finished() noexcept
115 : {
116 299 : state_->sched_.work_finished();
117 299 : }
118 :
119 : protected:
120 : // Override in derived to add pre-close logic (e.g. kqueue linger reset)
121 MIS 0 : void pre_shutdown(Impl*) noexcept {}
122 HIT 154 : void pre_destroy(Impl*) noexcept {}
123 :
124 : std::unique_ptr<state_type> state_;
125 :
126 : private:
127 : reactor_socket_service(reactor_socket_service const&) = delete;
128 : reactor_socket_service& operator=(reactor_socket_service const&) = delete;
129 : };
130 :
131 : } // namespace boost::corosio::detail
132 :
133 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_SERVICE_HPP
|