Branch data Line data Source code
1 : : /*
2 : : * Copyright 2025 Jinwoo Sung
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #pragma once
18 : :
19 : : #include <memory>
20 : : #include <optional>
21 : : #include <string>
22 : : #include <vector>
23 : :
24 : : #include "wirestead/base/visibility.hpp"
25 : : #include "wirestead/config/serial_config.hpp"
26 : : #include "wirestead/diagnostics/error_types.hpp"
27 : : #include "wirestead/interface/result_channel.hpp"
28 : : #include "wirestead/wrapper/send_result.hpp"
29 : :
30 : : namespace boost {
31 : : namespace asio {
32 : : class io_context;
33 : : }
34 : : } // namespace boost
35 : :
36 : : namespace wirestead {
37 : :
38 : : namespace interface {
39 : : class SerialPortInterface;
40 : : }
41 : :
42 : : namespace wrapper {
43 : : class Serial;
44 : : }
45 : : namespace transport {
46 : : namespace detail {
47 : : struct SerialWriteWait;
48 : : }
49 : :
50 : : /**
51 : : * @brief Serial Transport implementation
52 : : */
53 : : class WIRESTEAD_API Serial : public interface::ResultChannel, public std::enable_shared_from_this<Serial> {
54 : : public:
55 : : // use_shared_context: opt into the shared IoContextManager singleton
56 : : // instead of the default dedicated io_context + thread. Only meaningful
57 : : // for multi-instance-per-process deployments deliberately trading
58 : : // parallelism for reduced thread/memory overhead (#440); most callers
59 : : // should leave this false.
60 : : static std::shared_ptr<Serial> create(const config::SerialConfig& cfg, bool use_shared_context = false);
61 : : static std::shared_ptr<Serial> create(const config::SerialConfig& cfg, boost::asio::io_context& ioc);
62 : : static std::shared_ptr<Serial> create(const config::SerialConfig& cfg,
63 : : std::unique_ptr<interface::SerialPortInterface> port,
64 : : boost::asio::io_context& ioc);
65 : : ~Serial() override;
66 : :
67 : : // Move semantics
68 : : Serial(Serial&&) noexcept;
69 : : Serial& operator=(Serial&&) noexcept;
70 : :
71 : : // Non-copyable
72 : : Serial(const Serial&) = delete;
73 : : Serial& operator=(const Serial&) = delete;
74 : :
75 : : // Channel implementation
76 : : void start() override;
77 : : void stop() override;
78 : : bool is_connected() const override;
79 : : bool is_backpressure_active() const override;
80 : : std::optional<size_t> write_queue_limit() const override;
81 : : wrapper::RuntimeStats stats() const override;
82 : : void reset_stats() override;
83 : : std::optional<diagnostics::ErrorInfo> last_error_info() const override;
84 : : boost::asio::any_io_executor get_executor() override;
85 : :
86 : : [[nodiscard]] wrapper::SendResult async_write_copy_result(memory::ConstByteSpan data) override;
87 : : [[nodiscard]] wrapper::SendResult async_write_move_result(std::vector<uint8_t>&& data) override;
88 : : [[nodiscard]] wrapper::SendResult async_write_shared_result(
89 : : std::shared_ptr<const std::vector<uint8_t>> data) override;
90 : : [[nodiscard]] wrapper::SendResult async_try_write_copy_result(memory::ConstByteSpan data) override;
91 : : [[nodiscard]] wrapper::SendResult async_try_write_move_result(std::vector<uint8_t>&& data) override;
92 : : [[nodiscard]] wrapper::SendResult async_try_write_shared_result(
93 : : std::shared_ptr<const std::vector<uint8_t>> data) override;
94 : :
95 : : void on_bytes(OnBytes cb) override;
96 : : void on_state(OnState cb) override;
97 : : void on_backpressure(OnBackpressure cb) override;
98 : :
99 : : void set_backpressure_strategy(base::constants::BackpressureStrategy strategy);
100 : : void set_retry_interval(unsigned interval_ms);
101 : :
102 : : private:
103 : : // The built-in wrapper pins capacity waits without extending Channel's ABI.
104 : : friend class wrapper::Serial;
105 : : void fail_receive();
106 : : std::optional<uint64_t> write_connection() const;
107 : : std::shared_ptr<detail::SerialWriteWait> capture_write_wait() const;
108 : : std::optional<wrapper::SendResult> poll_write_wait(const std::shared_ptr<detail::SerialWriteWait>& wait) const;
109 : : void cancel_write_waits();
110 : : wrapper::SendResult write_state();
111 : : // Native admission only: wrapper lifecycle, validation precedence and
112 : : // strategy-level reason mapping remain the wrapper's responsibility.
113 : : wrapper::SendResult write_copy(memory::ConstByteSpan data, std::optional<uint64_t> expected_connection);
114 : : wrapper::SendResult write_move(std::vector<uint8_t>&& data, std::optional<uint64_t> expected_connection);
115 : : wrapper::SendResult write_shared(std::shared_ptr<const std::vector<uint8_t>> data,
116 : : std::optional<uint64_t> expected_connection);
117 : :
118 : : wrapper::SendResult try_write_copy(memory::ConstByteSpan data);
119 : : wrapper::SendResult try_write_move(std::vector<uint8_t>&& data);
120 : : wrapper::SendResult try_write_shared(std::shared_ptr<const std::vector<uint8_t>> data);
121 : :
122 : : explicit Serial(const config::SerialConfig& cfg, bool use_shared_context);
123 : : Serial(const config::SerialConfig& cfg, std::unique_ptr<interface::SerialPortInterface> port,
124 : : boost::asio::io_context& ioc);
125 : :
126 : : struct Impl;
127 : 2228 : const Impl* get_impl() const { return impl_.get(); }
128 : 2542 : Impl* get_impl() { return impl_.get(); }
129 : : std::unique_ptr<Impl> impl_;
130 : : };
131 : : } // namespace transport
132 : : } // namespace wirestead
|