/* * Copyright (c) 2017-2023 zhllxt * * author : zhllxt * email : 37792738@qq.com * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef __ASIO2_RDC_OPTION_HPP__ #define __ASIO2_RDC_OPTION_HPP__ #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #include #include #include namespace asio2::rdc { struct option_base { virtual ~option_base() {} virtual std::any call_parser(bool is_send, void* data) = 0; virtual void emplace_request(std::any& k, void* v) = 0; virtual void execute_and_erase(std::any& k, std::function cb) = 0; virtual void foreach_and_clear(std::function cb) = 0; }; template class option : public rdc::option_base { protected: using send_parser_fun = std::function; using recv_parser_fun = std::function; send_parser_fun rdc_send_parser_; recv_parser_fun rdc_recv_parser_; using invoker_type = detail::rdc_invoker_t; using iterator_type = typename invoker_type::iterator_type; using key_type = IdT; using val_type = typename invoker_type::value_type; invoker_type rdc_invoker_; public: option(option&&) noexcept = default; option(option const&) = default; option& operator=(option&&) noexcept = default; option& operator=(option const&) = default; template>, int> = 0> explicit option(ParserFun&& parser) : rdc_send_parser_(std::forward(parser)) , rdc_recv_parser_(rdc_send_parser_) { } template explicit option(SendParserFun&& send_parser, RecvParserFun&& recv_parser) : rdc_send_parser_(std::forward(send_parser)) , rdc_recv_parser_(std::forward(recv_parser)) { } template option& set_send_parser(ParserFun&& parser) { rdc_send_parser_ = std::forward(parser); return (*this); } template option& set_recv_parser(ParserFun&& parser) { rdc_recv_parser_ = std::forward(parser); return (*this); } send_parser_fun& get_send_parser() noexcept { return rdc_send_parser_; } recv_parser_fun& get_recv_parser() noexcept { return rdc_recv_parser_; } detail::rdc_invoker_t& invoker() noexcept { return rdc_invoker_; } virtual std::any call_parser(bool is_send, void* data) override { if (is_send) { typename detail::remove_cvref_t& d = *((typename detail::remove_cvref_t*)data); key_type id = rdc_send_parser_(d); return std::any(std::move(id)); } else { typename detail::remove_cvref_t& d = *((typename detail::remove_cvref_t*)data); key_type id = rdc_recv_parser_(d); return std::any(std::move(id)); } } virtual void emplace_request(std::any& k, void* v) override { key_type& key = *std::any_cast(std::addressof(k)); val_type& val = *((val_type*)v); // 2023-07-11 bug fix : can't use std::move(key), beacuse the key will be used at later. rdc_invoker_.emplace(key, std::move(val)); } virtual void execute_and_erase(std::any& k, std::function cb) override { key_type& key = *std::any_cast(std::addressof(k)); if (auto iter = rdc_invoker_.find(key); iter != rdc_invoker_.end()) { cb((void*)(std::addressof(iter->second))); rdc_invoker_.erase(iter); } } virtual void foreach_and_clear(std::function cb) override { for (auto& [k, v] : rdc_invoker_.reqs()) { cb((void*)std::addressof(k), (void*)std::addressof(v)); } rdc_invoker_.reqs().clear(); } }; // C++17 class template argument deduction guides template option(ParserFun)->option< typename detail::function_traits>::return_type, typename detail::function_traits>::template args<0>::type, typename detail::function_traits>::template args<0>::type >; template option(SendParserFun, RecvParserFun)->option< typename detail::function_traits>::return_type, typename detail::function_traits>::template args<0>::type, typename detail::function_traits>::template args<0>::type >; } #endif // !__ASIO2_RDC_OPTION_HPP__