123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- #ifndef __ASIO2_SESSION_MGR_HPP__
- #define __ASIO2_SESSION_MGR_HPP__
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- #pragma once
- #endif
- #include <algorithm>
- #include <memory>
- #include <functional>
- #include <unordered_map>
- #include <type_traits>
- #include <asio2/base/iopool.hpp>
- #include <asio2/base/define.hpp>
- #include <asio2/base/log.hpp>
- #include <asio2/base/detail/allocator.hpp>
- #include <asio2/base/detail/util.hpp>
- #include <asio2/base/detail/shared_mutex.hpp>
- namespace asio2::detail
- {
- ASIO2_CLASS_FORWARD_DECLARE_BASE;
- ASIO2_CLASS_FORWARD_DECLARE_TCP_BASE;
- ASIO2_CLASS_FORWARD_DECLARE_TCP_SERVER;
- ASIO2_CLASS_FORWARD_DECLARE_TCP_SESSION;
- ASIO2_CLASS_FORWARD_DECLARE_UDP_BASE;
- ASIO2_CLASS_FORWARD_DECLARE_UDP_SERVER;
- ASIO2_CLASS_FORWARD_DECLARE_UDP_SESSION;
-
- template<class session_t>
- class session_mgr_t
- {
- friend session_t;
- ASIO2_CLASS_FRIEND_DECLARE_BASE;
- ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE;
- ASIO2_CLASS_FRIEND_DECLARE_TCP_SERVER;
- ASIO2_CLASS_FRIEND_DECLARE_TCP_SESSION;
- ASIO2_CLASS_FRIEND_DECLARE_UDP_BASE;
- ASIO2_CLASS_FRIEND_DECLARE_UDP_SERVER;
- ASIO2_CLASS_FRIEND_DECLARE_UDP_SESSION;
- protected:
- #if defined(_DEBUG) || defined(DEBUG)
- class [[maybe_unused]] deadlock_checker_value
- {
- public:
- [[maybe_unused]] static bool& get() noexcept
- {
- thread_local static bool b = false;
- return b;
- }
- };
- struct deadlock_checker_guard
- {
- deadlock_checker_guard(bool& b) : b_(b)
- {
- ASIO2_ASSERT(b_ == false);
- b_ = true;
- }
- ~deadlock_checker_guard()
- {
- ASIO2_ASSERT(b_ == true);
- b_ = false;
- }
- bool& b_;
- };
- #endif
- public:
- using self = session_mgr_t<session_t>;
- using args_type = typename session_t::args_type;
- using key_type = typename session_t::key_type;
-
- explicit session_mgr_t(std::shared_ptr<io_t> acceptor_io, std::atomic<state_t>& server_state)
- : io_ (std::move(acceptor_io))
- , state_(server_state)
- {
- this->sessions_.reserve(64);
- }
-
- ~session_mgr_t() = default;
-
- template<class Fun>
- inline void emplace(std::shared_ptr<session_t> session_ptr, Fun&& callback)
- {
- if (!session_ptr)
- return;
- asio::dispatch(this->io_->context(), make_allocator(this->allocator_,
- [this, session_ptr = std::move(session_ptr), callback = std::forward<Fun>(callback)]
- () mutable
- {
- bool inserted = false;
-
-
-
-
-
- if (this->state_ == state_t::started)
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(is_all_session_stop_called_ == false);
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
-
-
-
- asio2::unique_locker guard(this->mutex_);
- inserted = this->sessions_.try_emplace(session_ptr->hash_key(), session_ptr).second;
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(is_all_session_stop_called_ == false);
- #endif
- }
- (callback)(inserted);
- }));
- }
-
- template<class Fun>
- inline void erase(std::shared_ptr<session_t> session_ptr, Fun&& callback)
- {
- if (!session_ptr)
- return;
- asio::dispatch(this->io_->context(), make_allocator(this->allocator_,
- [this, session_ptr = std::move(session_ptr), callback = std::forward<Fun>(callback)]
- () mutable
- {
- bool erased = false;
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
- {
- asio2::unique_locker guard(this->mutex_);
- erased = (this->sessions_.erase(session_ptr->hash_key()) > 0);
- }
- (callback)(erased);
- }));
- }
-
- template<class Fun>
- inline void post(Fun&& task)
- {
- asio::post(this->io_->context(), make_allocator(this->allocator_, std::forward<Fun>(task)));
- }
-
- template<class Fun>
- inline void dispatch(Fun&& task)
- {
- asio::dispatch(this->io_->context(), make_allocator(this->allocator_, std::forward<Fun>(task)));
- }
-
- template<class Fun>
- inline void for_each(Fun&& fn)
- {
-
-
- std::vector<std::shared_ptr<session_t>> sessions;
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
- {
- asio2::shared_locker guard(this->mutex_);
- sessions.reserve(this->sessions_.size());
- for (const auto& [k, session_ptr] : this->sessions_)
- {
- std::ignore = k;
- sessions.emplace_back(session_ptr);
- }
- }
- for (std::shared_ptr<session_t>& session_ptr : sessions)
- {
- fn(session_ptr);
- }
-
-
-
-
-
-
-
-
-
- }
-
- template<class Fun>
- inline void quick_for_each(Fun&& fn)
- {
-
-
- asio2::shared_locker guard(this->mutex_);
- #if defined(_DEBUG) || defined(DEBUG)
- [[maybe_unused]] deadlock_checker_guard leg(deadlock_checker_value::get());
- #endif
- for (auto& [k, session_ptr] : this->sessions_)
- {
- std::ignore = k;
- fn(session_ptr);
- }
- }
-
- inline std::shared_ptr<session_t> find(const key_type & key)
- {
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
- asio2::shared_locker guard(this->mutex_);
- auto iter = this->sessions_.find(key);
- return (iter == this->sessions_.end() ? std::shared_ptr<session_t>() : iter->second);
- }
-
- template<class Fun>
- inline std::shared_ptr<session_t> find_if(Fun&& fn)
- {
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
-
- asio2::shared_locker guard(this->mutex_);
- auto iter = std::find_if(this->sessions_.begin(), this->sessions_.end(),
- [&fn](auto &pair) mutable
- {
- return fn(pair.second);
- });
- return (iter == this->sessions_.end() ? std::shared_ptr<session_t>() : iter->second);
- }
-
- inline std::size_t size() const noexcept
- {
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
- asio2::shared_locker guard(this->mutex_);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return this->sessions_.size();
- }
-
- inline bool empty() const noexcept
- {
- #if defined(_DEBUG) || defined(DEBUG)
- ASIO2_ASSERT(deadlock_checker_value::get() == false);
- #endif
- asio2::shared_locker guard(this->mutex_);
- return this->sessions_.empty();
- }
-
- inline io_t & io() noexcept
- {
- return (*this->io_);
- }
-
- inline io_t const& io() const noexcept
- {
- return (*this->io_);
- }
- protected:
-
- mutable asio2::shared_mutexer mutex_;
-
- std::unordered_map<key_type, std::shared_ptr<session_t>> sessions_ ASIO2_GUARDED_BY(mutex_);
-
- std::shared_ptr<io_t> io_;
-
- handler_memory<std::false_type, assizer<args_type>> allocator_;
-
- std::atomic<state_t> & state_;
- #if defined(_DEBUG) || defined(DEBUG)
- bool is_all_session_stop_called_ = false;
- #endif
- };
- }
- #endif
|