19 #include <boost/asio/executor_work_guard.hpp>
20 #include <boost/asio/io_context.hpp>
46 std::unique_ptr<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>
work_guard_;
64 Impl(
const std::string& host, uint16_t port, std::shared_ptr<boost::asio::io_context> external_ioc)
72 explicit Impl(std::shared_ptr<interface::Channel> channel)
85 std::lock_guard<std::mutex> lock(
mutex_);
96 std::lock_guard<std::mutex> lock(
mutex_);
100 return p.get_future();
102 std::promise<bool> p;
103 auto f = p.get_future();
120 work_guard_ = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(
124 while (
started_.load() && !ioc->stopped()) {
125 if (ioc->run_one_for(std::chrono::milliseconds(50)) == 0) {
126 std::this_thread::yield();
137 bool should_join =
false;
139 std::unique_lock<std::mutex> lock(mutex_);
140 if (!started_.load()) {
141 for (
auto& p : pending_promises_) {
147 pending_promises_.clear();
152 channel_->on_bytes(
nullptr);
153 channel_->on_state(
nullptr);
156 if (use_external_context_ && manage_external_context_) {
157 if (work_guard_) work_guard_.reset();
158 if (external_ioc_) external_ioc_->stop();
161 for (
auto& p : pending_promises_) {
167 pending_promises_.clear();
169 if (should_join && external_thread_.joinable()) {
171 external_thread_.join();
175 std::lock_guard<std::mutex> lock(mutex_);
179 void send(std::string_view data) {
180 if (channel_ && channel_->is_connected()) {
186 bool is_connected()
const {
return channel_ && channel_->is_connected(); }
189 if (!channel_)
return;
191 std::weak_ptr<bool> weak_alive = alive_marker_;
196 if (weak_alive.expired())
return;
204 if (weak_alive.expired())
return;
213 bool handled =
false;
214 if (
auto transport = std::dynamic_pointer_cast<transport::TcpClient>(channel_)) {
215 if (
auto info = transport->last_error_info()) {
231 : impl_(std::make_unique<
Impl>(h, p, ioc)) {}
245 impl_->data_handler_ = std::move(h);
249 impl_->connect_handler_ = std::move(h);
253 impl_->disconnect_handler_ = std::move(h);
257 impl_->error_handler_ = std::move(h);
262 impl_->auto_manage_ = m;
263 if (impl_->auto_manage_ && !impl_->started_.load())
start();
268 impl_->retry_interval_ = i;
269 if (impl_->channel_) {
270 auto transport_client = std::dynamic_pointer_cast<transport::TcpClient>(impl_->channel_);
271 if (transport_client) transport_client->set_retry_interval(
static_cast<unsigned int>(i.count()));
277 impl_->max_retries_ = m;
281 impl_->connection_timeout_ = t;
285 impl_->manage_external_context_ = m;
static std::shared_ptr< interface::Channel > create(const ChannelOptions &options, std::shared_ptr< boost::asio::io_context > external_ioc=nullptr)
A C++17 compatible span-like class for safe array access.
constexpr size_type size() const noexcept
constexpr pointer data() const noexcept
Common interface for 1:1 point-to-point communication (e.g., TcpClient, Serial, Udp)
std::function< void(const ErrorContext &)> ErrorHandler
std::function< void(const MessageContext &)> MessageHandler
std::function< void(const ConnectionContext &)> ConnectionHandler
Modernized TCP Client Wrapper.
ChannelInterface & on_error(ErrorHandler handler) override
TcpClient & set_manage_external_context(bool manage)
ChannelInterface & auto_manage(bool manage=true) override
ChannelInterface & on_connect(ConnectionHandler handler) override
void send(std::string_view data) override
ChannelInterface & on_disconnect(ConnectionHandler handler) override
void send_line(std::string_view line) override
TcpClient & set_retry_interval(std::chrono::milliseconds interval)
TcpClient & set_connection_timeout(std::chrono::milliseconds timeout)
ChannelInterface & on_data(MessageHandler handler) override
TcpClient & set_max_retries(int max_retries)
bool is_connected() const override
TcpClient(const std::string &host, uint16_t port)
std::future< bool > start() override
std::string uint8_to_string(const uint8_t *data, size_t size)
Safely convert uint8_t* to const char* for string operations.
std::pair< const uint8_t *, size_t > string_to_bytes(std::string_view str)
Safely obtain a view of std::string as byte array without allocation.
wrapper::ErrorContext to_error_context(const diagnostics::ErrorInfo &info, std::optional< size_t > client_id=std::nullopt)
Converts ErrorInfo to wrapper::ErrorContext.
wrapper::ConnectionContext ConnectionContext
wrapper::ErrorContext ErrorContext
wrapper::MessageContext MessageContext
unsigned connection_timeout_ms
unsigned retry_interval_ms
ConnectionHandler disconnect_handler_
std::chrono::milliseconds connection_timeout_
Impl(std::shared_ptr< interface::Channel > channel)
bool is_connected() const
std::shared_ptr< boost::asio::io_context > external_ioc_
std::atomic< bool > started_
std::vector< std::promise< bool > > pending_promises_
bool manage_external_context_
std::thread external_thread_
Impl(const std::string &host, uint16_t port)
void setup_internal_handlers()
ErrorHandler error_handler_
void send(std::string_view data)
std::unique_ptr< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_guard_
std::shared_ptr< bool > alive_marker_
ConnectionHandler connect_handler_
std::chrono::milliseconds retry_interval_
std::future< bool > start()
Impl(const std::string &host, uint16_t port, std::shared_ptr< boost::asio::io_context > external_ioc)
MessageHandler data_handler_
std::shared_ptr< interface::Channel > channel_
bool use_external_context_
void fulfill_all(bool value)