123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #ifndef __ASIO2_SHUTDOWN_COMPONENT_HPP__
- #define __ASIO2_SHUTDOWN_COMPONENT_HPP__
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- #pragma once
- #endif
- #include <memory>
- #include <future>
- #include <utility>
- #include <string_view>
- #include <asio2/base/iopool.hpp>
- #include <asio2/base/listener.hpp>
- #include <asio2/base/impl/event_queue_cp.hpp>
- namespace asio2::detail
- {
- template<class derived_t, class args_t>
- class shutdown_cp
- {
- public:
- using self = shutdown_cp<derived_t, args_t>;
- public:
-
- shutdown_cp() noexcept {}
-
- ~shutdown_cp() = default;
- protected:
- template<typename DeferEvent>
- inline void _do_shutdown(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ASIO2_ASSERT(derive.io_->running_in_this_thread());
- ASIO2_LOG_DEBUG("shutdown_cp::_do_shutdown enter: {} {}", ec.value(), ec.message());
-
-
-
-
-
-
-
-
-
- if (derive.shutdown_timer_ || derive.disconnecting_)
- {
- derive._stop_shutdown_timer(std::move(this_ptr));
- return;
- }
- derive.disp_event(
- [&derive, ec, this_ptr = std::move(this_ptr), e = chain.move_event()]
- (event_queue_guard<derived_t> g) mutable
- {
- set_last_error(ec);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- defer_event chain(std::move(e), std::move(g));
- ASIO2_LOG_DEBUG("shutdown_cp::_do_shutdown leave: {} {} state={}",
- ec.value(), ec.message(), detail::to_string(derive.state_.load()));
- state_t expected = state_t::started;
- if (derive.state_.compare_exchange_strong(expected, state_t::started))
- {
- derive.disconnecting_ = true;
- return derive._post_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
- expected = state_t::starting;
- if (derive.state_.compare_exchange_strong(expected, state_t::starting))
- {
- derive.disconnecting_ = true;
- return derive._post_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
- asio::post(derive.io_->context(), make_allocator(derive.wallocator(),
- [this_ptr = std::move(this_ptr), chain = std::move(chain)]() mutable
- {
- detail::ignore_unused(this_ptr, chain);
- }));
- }, chain.move_guard());
- }
- template<typename DeferEvent>
- inline void _post_shutdown(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- ASIO2_ASSERT(derive.io_->running_in_this_thread());
- ASIO2_LOG_DEBUG("shutdown_cp::_post_shutdown: {} {}", ec.value(), ec.message());
- if constexpr (std::is_same_v<typename derived_t::socket_type::protocol_type, asio::ip::tcp>)
- {
- derive._post_shutdown_tcp(ec, std::move(this_ptr), std::move(chain));
- }
- else
- {
- derive._handle_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
- }
- template<typename DeferEvent>
- inline void _post_shutdown_tcp(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
-
- if (derive.socket().is_open())
- {
- error_code ec_linger{};
- asio::socket_base::linger lnger{};
- derive.socket().lowest_layer().get_option(lnger, ec_linger);
-
-
-
- if (!ec_linger && !(lnger.enabled() == true && lnger.timeout() == 0))
- {
- error_code ec_shutdown{};
- derive.socket().shutdown(asio::socket_base::shutdown_send, ec_shutdown);
-
-
-
-
-
-
-
-
-
-
-
- if (!ec_shutdown && derive.reading_)
- {
- derive._make_shutdown_timer(ec, std::move(this_ptr), std::move(chain));
- return;
- }
- }
- }
- derive._handle_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
- template<typename DeferEvent>
- inline void _handle_shutdown(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- ASIO2_ASSERT(derive.io_->running_in_this_thread());
- ASIO2_LOG_DEBUG("shutdown_cp::_handle_shutdown: {} {}", ec.value(), ec.message());
- this->shutdown_timer_.reset();
- derive._do_close(ec, std::move(this_ptr), std::move(chain));
- }
- protected:
- template<typename DeferEvent>
- inline void _make_shutdown_timer(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- ASIO2_ASSERT(derive.io_->running_in_this_thread());
- asio::dispatch(derive.io_->context(), make_allocator(derive.wallocator(),
- [this, ec, this_ptr = std::move(this_ptr), chain = std::move(chain)]() mutable
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- ASIO2_ASSERT(this->shutdown_timer_ == nullptr);
- if (this->shutdown_timer_)
- {
- this->shutdown_timer_->cancel();
- }
- this->shutdown_timer_ = std::make_shared<safe_timer>(derive.io_->context());
- derive._post_shutdown_timer(ec, std::move(this_ptr), std::move(chain),
- derive.get_disconnect_timeout(), this->shutdown_timer_);
- }));
- }
- template<typename DeferEvent, class Rep, class Period>
- inline void _post_shutdown_timer(
- const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain,
- std::chrono::duration<Rep, Period> duration, std::shared_ptr<safe_timer> timer_ptr)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
-
- if (timer_ptr.get() != this->shutdown_timer_.get())
- return;
- safe_timer* ptimer = timer_ptr.get();
- ptimer->timer.expires_after(duration);
- ptimer->timer.async_wait(
- [&derive, ec, this_ptr = std::move(this_ptr), chain = std::move(chain), timer_ptr = std::move(timer_ptr)]
- (const error_code& timer_ec) mutable
- {
- derive._handle_shutdown_timer(
- timer_ec, ec, std::move(this_ptr), std::move(chain), std::move(timer_ptr));
- });
- }
- template<typename DeferEvent>
- inline void _handle_shutdown_timer(
- const error_code& timer_ec,
- const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain,
- std::shared_ptr<safe_timer> timer_ptr)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- ASIO2_ASSERT((!timer_ec) || timer_ec == asio::error::operation_aborted);
-
- if (timer_ptr.get() != this->shutdown_timer_.get())
- return;
-
- if (!this->shutdown_timer_)
- {
- ASIO2_ASSERT(false);
- return;
- }
-
- if (timer_ec == asio::error::operation_aborted || timer_ptr->canceled.test_and_set())
- {
- timer_ptr->canceled.clear();
- ASIO2_LOG_DEBUG("shutdown_cp::_handle_shutdown_timer: canceled");
- derive._handle_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
-
- else
- {
- timer_ptr->canceled.clear();
- std::chrono::system_clock::duration silence = derive.get_silence_duration();
-
- if (silence < derive.get_disconnect_timeout())
- {
- derive._post_shutdown_timer(ec, std::move(this_ptr), std::move(chain),
- derive.get_disconnect_timeout() - silence, std::move(timer_ptr));
- }
- else
- {
- ASIO2_LOG_DEBUG("shutdown_cp::_handle_shutdown_timer: timeout");
- derive._handle_shutdown(ec, std::move(this_ptr), std::move(chain));
- }
- }
- }
- inline void _stop_shutdown_timer(std::shared_ptr<derived_t> this_ptr)
- {
- derived_t& derive = static_cast<derived_t&>(*this);
- asio::dispatch(derive.io_->context(), make_allocator(derive.wallocator(),
- [this, this_ptr = std::move(this_ptr)]() mutable
- {
- if (this->shutdown_timer_)
- {
- this->shutdown_timer_->cancel();
- }
- }));
- }
- protected:
-
-
- std::shared_ptr<safe_timer> shutdown_timer_;
- };
- }
- #endif
|