82 :
public ThreadType<IOConfig>,
84 IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig,
85 SocketType, ThreadType, use_indexed_groups>,
86 line_in_group, publish_layer,
87 typename ThreadType<IOConfig>::Transporter::implementation_tag, use_indexed_groups>,
89 IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig,
90 SocketType, ThreadType, use_indexed_groups>,
91 line_out_group, subscribe_layer,
92 typename ThreadType<IOConfig>::Transporter::implementation_tag, use_indexed_groups>
100 : ThreadType<IOConfig>(config,
this->loop_max_frequency(), index),
102 IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig,
103 SocketType, ThreadType, use_indexed_groups>,
104 line_in_group, publish_layer,
105 typename ThreadType<IOConfig>::Transporter::implementation_tag, use_indexed_groups>(
108 IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig,
109 SocketType, ThreadType, use_indexed_groups>,
110 line_out_group, subscribe_layer,
111 typename ThreadType<IOConfig>::Transporter::implementation_tag, use_indexed_groups>(
116 auto data_out_callback =
117 [
this](std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg)
119 if (!io_msg->has_index() || io_msg->index() ==
this->index())
125 this->
template subscribe_out<goby::middleware::protobuf::IOData>(data_out_callback);
127 if (!glog_group_added_)
130 glog_group_added_ =
true;
137 incoming_mail_notify_thread_.reset(
new std::thread(
140 while (this->alive())
142 std::unique_lock<std::mutex> lock(incoming_mail_notify_mutex_);
143 this->interthread().cv()->wait(lock);
145 boost::asio::post(io_, []() {});
149 this->set_name(thread_name_);
156 std::lock_guard<std::mutex> l(incoming_mail_notify_mutex_);
157 this->interthread().cv()->notify_all();
159 incoming_mail_notify_thread_->join();
160 incoming_mail_notify_thread_.reset();
168 if (incoming_mail_notify_thread_)
169 incoming_mail_notify_thread_->detach();
171 auto status = std::make_shared<protobuf::IOStatus>();
174 this->publish_in(status);
175 this->
template unsubscribe_out<goby::middleware::protobuf::IOData>();
178 template <
class IOThreadImplementation>
180 std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg);
183 void write(std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg)
186 goby::glog <<
group(glog_group_) <<
"(" << io_msg->data().size() <<
"B) <"
187 << ((this->index() == -1) ? std::string() : std::to_string(this->index()))
188 <<
" " << io_msg->ShortDebugString() << std::endl;
189 if (io_msg->data().empty())
191 if (!socket_ || !socket_->is_open())
199 auto io_msg = std::make_shared<goby::middleware::protobuf::IOData>();
200 *io_msg->mutable_data() = bytes;
206 std::shared_ptr<goby::middleware::protobuf::IOData> io_msg)
208 if (this->index() != -1)
209 io_msg->set_index(this->index());
213 << ((this->index() == -1) ? std::string() : std::to_string(this->index()))
214 <<
" " << io_msg->ShortDebugString() << std::endl;
216 this->publish_in(io_msg);
244 virtual void async_write(std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg) = 0;
253 void loop()
override;
257 std::unique_ptr<SocketType> socket_;
264 std::mutex incoming_mail_notify_mutex_;
265 std::unique_ptr<std::thread> incoming_mail_notify_thread_;
267 std::string glog_group_;
268 std::string thread_name_;
269 bool glog_group_added_{
false};
272template <
class IOThreadImplementation>
274 std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg)
276 boost::asio::async_write(
277 this_thread->mutable_socket(), boost::asio::buffer(io_msg->data()),
279 [this_thread, io_msg](
const boost::system::error_code& ec, std::size_t bytes_transferred)
281 if (!ec && bytes_transferred > 0)
283 this_thread->handle_write_success(bytes_transferred);
287 this_thread->handle_write_error(ec);
301 template <
class>
class ThreadType,
bool use_indexed_groups>
303 subscribe_layer, IOConfig, SocketType, ThreadType,
304 use_indexed_groups>::try_open()
308 socket_.reset(
new SocketType(io_));
318 backoff_interval_ = min_backoff_interval_;
320 auto status = std::make_shared<protobuf::IOStatus>();
321 if (this->
index() != -1)
324 status->set_state(protobuf::IO__LINK_OPEN);
325 this->publish_in(status);
332 next_open_attempt_ = now + backoff_interval_;
334 catch (
const std::exception& e)
336 auto status = std::make_shared<protobuf::IOStatus>();
337 if (this->
index() != -1)
340 status->set_state(protobuf::IO__CRITICAL_FAILURE);
343 error.set_text(
e.what() + std::string(
": config (") +
this->cfg().ShortDebugString() +
")");
344 this->publish_in(status);
347 <<
"Failed to open/configure socket/serial_port: "
348 <<
error.ShortDebugString() << std::endl;
350 if (backoff_interval_ < max_backoff_interval_)
351 backoff_interval_ *= 2.0;
354 next_open_attempt_ = now + backoff_interval_;
357 << backoff_interval_ / std::chrono::seconds(1)
358 <<
" seconds" << std::endl;
367 template <
class>
class ThreadType,
bool use_indexed_groups>
369 subscribe_layer, IOConfig, SocketType, ThreadType,
370 use_indexed_groups>::loop()
372 if (socket_ && socket_->is_open())
382 if (now > next_open_attempt_)
399 template <
class>
class ThreadType,
bool use_indexed_groups>
401 line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig, SocketType, ThreadType,
404 auto status = std::make_shared<protobuf::IOStatus>();
405 if (this->index() != -1)
406 status->set_index(this->index());
411 error.set_text(ec.message());
412 this->publish_in(status);
415 <<
"Failed to read from the socket/serial_port: "
416 << error.ShortDebugString() << std::endl;
425 template <
class>
class ThreadType,
bool use_indexed_groups>
427 line_in_group, line_out_group, publish_layer, subscribe_layer, IOConfig, SocketType, ThreadType,
430 auto status = std::make_shared<protobuf::IOStatus>();
431 if (this->index() != -1)
432 status->set_index(this->index());
437 error.set_text(ec.message());
438 this->publish_in(status);
441 <<
"Failed to write to the socket/serial_port: "
442 << error.ShortDebugString() << std::endl;