From afbf62439dcbfef2670b4767e8ceca5c7bfebe8e Mon Sep 17 00:00:00 2001 From: youngwolf Date: Tue, 1 Nov 2016 21:16:04 +0800 Subject: [PATCH] 1.1.2 release. Fix bug: ascs::list cannot be moved properly via moving constructor. Use ASCS_DELAY_CLOSE instead of ASCS_ENHANCED_STABILITY macro to control delay close duration, 0 is an equivalent of defining ASCS_ENHANCED_STABILITY, other values keep the same meanings as before. Move ascs::socket::closing related logic to ascs::object. Make ascs::socket::id(uint_fast64_t) private to avoid changing IDs by users. Call close at the end of shutdown function, just for safety. Add move capture in lambda. Optimize lambda expressions. --- examples/client/client.cpp | 5 +- examples/echo_client/echo_client.cpp | 7 +- examples/file_client/file_client.cpp | 4 +- examples/file_server/file_server.cpp | 2 +- examples/file_server/file_socket.cpp | 2 +- examples/pingpong_client/pingpong_client.cpp | 5 +- examples/pingpong_server/pingpong_server.cpp | 3 +- examples/udp_test/udp_test.cpp | 3 + include/ascs/config.h | 34 +++++----- include/ascs/container.h | 16 ++--- include/ascs/object.h | 68 +++++++++----------- include/ascs/object_pool.h | 6 +- include/ascs/socket.h | 45 +++++-------- include/ascs/ssl/ssl.h | 13 ++-- include/ascs/tcp/socket.h | 3 +- include/ascs/udp/socket.h | 3 +- 16 files changed, 108 insertions(+), 111 deletions(-) diff --git a/examples/client/client.cpp b/examples/client/client.cpp index d63f6cb..278343b 100644 --- a/examples/client/client.cpp +++ b/examples/client/client.cpp @@ -2,7 +2,10 @@ #include //configuration -#define ASCS_SERVER_PORT 9527 +#define ASCS_SERVER_PORT 9527 +#define ASCS_DELAY_CLOSE 1 //this demo not used object pool and doesn't need life cycle management, + //so, define this to avoid hooks for async call (and slightly improve efficiency), + //any value which is bigger than zero is okay. #define ASCS_FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer #define ASCS_CUSTOM_LOG #define ASCS_DEFAULT_UNPACKER non_copy_unpacker diff --git a/examples/echo_client/echo_client.cpp b/examples/echo_client/echo_client.cpp index 65bf627..80ec161 100644 --- a/examples/echo_client/echo_client.cpp +++ b/examples/echo_client/echo_client.cpp @@ -2,14 +2,15 @@ #include //configuration -#define ASCS_SERVER_PORT 9527 +#define ASCS_SERVER_PORT 9527 //#define ASCS_REUSE_OBJECT //use objects pool +#define ASCS_DELAY_CLOSE 5 //define this to avoid hooks for async call (and slightly improve efficiency) //#define ASCS_FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer -//#define ASCS_CLEAR_OBJECT_INTERVAL 1 +//#define ASCS_CLEAR_OBJECT_INTERVAL 1 //#define ASCS_WANT_MSG_SEND_NOTIFY #define ASCS_FULL_STATISTIC //full statistic will slightly impact efficiency #ifdef ASCS_WANT_MSG_SEND_NOTIFY -#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks. +#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks #define ASCS_INPUT_CONTAINER list #endif //configuration diff --git a/examples/file_client/file_client.cpp b/examples/file_client/file_client.cpp index 6e8adb3..3499940 100644 --- a/examples/file_client/file_client.cpp +++ b/examples/file_client/file_client.cpp @@ -2,7 +2,9 @@ #include //configuration -#define ASCS_SERVER_PORT 5050 +#define ASCS_SERVER_PORT 5050 +#define ASCS_DELAY_CLOSE 5 //define this to avoid hooks for async call (and slightly improve efficiency) +//#define ASCS_INPUT_QUEUE non_lock_queue //we cannot use non_lock_queue, because we also send messages (talking messages) out of ascs::socket::on_msg_send(). #define ASCS_DEFAULT_UNPACKER replaceable_unpacker<> //configuration diff --git a/examples/file_server/file_server.cpp b/examples/file_server/file_server.cpp index 7f8f196..ec86094 100644 --- a/examples/file_server/file_server.cpp +++ b/examples/file_server/file_server.cpp @@ -4,7 +4,7 @@ //configuration #define ASCS_SERVER_PORT 5050 #define ASCS_ASYNC_ACCEPT_NUM 5 -#define ASCS_CLEAR_OBJECT_INTERVAL 60 +#define ASCS_CLEAR_OBJECT_INTERVAL 60 #define ASCS_ENHANCED_STABILITY #define ASCS_WANT_MSG_SEND_NOTIFY #define ASCS_INPUT_QUEUE non_lock_queue diff --git a/examples/file_server/file_socket.cpp b/examples/file_server/file_socket.cpp index 348c2be..d3d2583 100644 --- a/examples/file_server/file_socket.cpp +++ b/examples/file_server/file_socket.cpp @@ -2,7 +2,7 @@ //configuration #define ASCS_SERVER_PORT 5050 #define ASCS_ASYNC_ACCEPT_NUM 5 -#define ASCS_CLEAR_OBJECT_INTERVAL 60 +#define ASCS_CLEAR_OBJECT_INTERVAL 60 #define ASCS_ENHANCED_STABILITY #define ASCS_WANT_MSG_SEND_NOTIFY #define ASCS_INPUT_QUEUE non_lock_queue diff --git a/examples/pingpong_client/pingpong_client.cpp b/examples/pingpong_client/pingpong_client.cpp index dbd568e..df9a771 100644 --- a/examples/pingpong_client/pingpong_client.cpp +++ b/examples/pingpong_client/pingpong_client.cpp @@ -2,12 +2,13 @@ #include //configuration -#define ASCS_SERVER_PORT 9527 +#define ASCS_SERVER_PORT 9527 #define ASCS_REUSE_OBJECT //use objects pool +#define ASCS_DELAY_CLOSE 5 //define this to avoid hooks for async call (and slightly improve efficiency) //#define ASCS_FORCE_TO_USE_MSG_RECV_BUFFER //#define ASCS_WANT_MSG_SEND_NOTIFY #define ASCS_MSG_BUFFER_SIZE 65536 -#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks. +#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks #define ASCS_INPUT_CONTAINER list #define ASCS_DEFAULT_UNPACKER stream_unpacker //non-protocol //configuration diff --git a/examples/pingpong_server/pingpong_server.cpp b/examples/pingpong_server/pingpong_server.cpp index b8046c8..3cf4d5f 100644 --- a/examples/pingpong_server/pingpong_server.cpp +++ b/examples/pingpong_server/pingpong_server.cpp @@ -5,8 +5,9 @@ #define ASCS_SERVER_PORT 9527 #define ASCS_ASYNC_ACCEPT_NUM 5 #define ASCS_REUSE_OBJECT //use objects pool +#define ASCS_DELAY_CLOSE 5 //define this to avoid hooks for async call (and slightly improve efficiency) //#define ASCS_FORCE_TO_USE_MSG_RECV_BUFFER -#define ASCS_MSG_BUFFER_SIZE 65536 +#define ASCS_MSG_BUFFER_SIZE 65536 #define ASCS_INPUT_QUEUE non_lock_queue #define ASCS_INPUT_CONTAINER list //if pingpong_client only send message in on_msg() or on_msg_handle(), which means a responsive system, a real pingpong test, diff --git a/examples/udp_test/udp_test.cpp b/examples/udp_test/udp_test.cpp index 81b6ab5..5a35d92 100644 --- a/examples/udp_test/udp_test.cpp +++ b/examples/udp_test/udp_test.cpp @@ -2,6 +2,9 @@ #include //configuration +#define ASCS_DELAY_CLOSE 1 //this demo not used object pool and doesn't need life cycle management, + //so, define this to avoid hooks for async call (and slightly improve efficiency), + //any value which is bigger than zero is okay. //#define ASCS_DEFAULT_PACKER replaceable_packer<> //#define ASCS_DEFAULT_UDP_UNPACKER replaceable_udp_unpacker<> //configuration diff --git a/include/ascs/config.h b/include/ascs/config.h index 883dbf7..eb70de1 100644 --- a/include/ascs/config.h +++ b/include/ascs/config.h @@ -35,18 +35,28 @@ * Add a new packer--fixed_length_packer. * Add a new class--message_queue. * - * 2016.10.16 version 1.3.1 + * 2016.10.16 version 1.1.1 * Support non-lock queue, it's totally not thread safe and lock-free, it can improve IO throughput with particular business. * Demonstrate how and when to use non-lock queue as the input and output message buffer. * Queues (and their internal containers) used as input and output message buffer are now configurable (by macros or template arguments). * New macros--ASCS_INPUT_QUEUE, ASCS_INPUT_CONTAINER, ASCS_OUTPUT_QUEUE and ASCS_OUTPUT_CONTAINER. * Drop macro ASCS_USE_CONCURRENT_QUEUE, rename macro ASCS_USE_CONCURRE to ASCS_HAS_CONCURRENT_QUEUE. * In contrast to non_lock_queue, split message_queue into lock_queue and lock_free_queue. - * Move container related classes and functions from st_asio_wrapper_base.h to st_asio_wrapper_container.h. + * Move container related classes and functions from base.h to container.h. * Improve efficiency in scenarios of low throughput like pingpong test. * Replaceable packer/unpacker now support replaceable_buffer (an alias of auto_buffer) and shared_buffer to be their message type. * Move class statistic and obj_with_begin_time out of ascs::socket to reduce template tiers. * + * 2016.1.1 version 1.1.2 + * Fix bug: ascs::list cannot be moved properly via moving constructor. + * Use ASCS_DELAY_CLOSE instead of ASCS_ENHANCED_STABILITY macro to control delay close duration, + * 0 is an equivalent of defining ASCS_ENHANCED_STABILITY, other values keep the same meanings as before. + * Move ascs::socket::closing related logic to ascs::object. + * Make ascs::socket::id(uint_fast64_t) private to avoid changing IDs by users. + * Call close at the end of shutdown function, just for safety. + * Add move capture in lambda. + * Optimize lambda expressions. + * */ #ifndef _ASCS_CONFIG_H_ @@ -56,8 +66,8 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#define ASCS_VER 10101 //[x]xyyzz -> [x]x.[y]y.[z]z -#define ASCS_VERSION "1.1.1" +#define ASCS_VER 10102 //[x]xyyzz -> [x]x.[y]y.[z]z +#define ASCS_VERSION "1.1.2" //asio and compiler check #ifdef _MSC_VER @@ -124,19 +134,13 @@ static_assert(ASCS_MAX_MSG_NUM > 0, "message capacity must be bigger than zero." //after this duration, this socket can be freed from the heap or reused, //you must define this macro as a value, not just define it, the value means the duration, unit is second. -//if macro ASCS_ENHANCED_STABILITY been defined, this macro will always be zero. -#ifdef ASCS_ENHANCED_STABILITY -#if defined(ASCS_DELAY_CLOSE) && ASCS_DELAY_CLOSE != 0 -#warning ASCS_DELAY_CLOSE will always be zero if ASCS_ENHANCED_STABILITY macro been defined. -#endif -#undef ASCS_DELAY_CLOSE -#define ASCS_DELAY_CLOSE 0 -#else +//a value equal to zero will cause ascs to use a mechanism to guarantee 100% safety when reusing or freeing this socket, +//ascs will hook all async calls to avoid this socket to be reused or freed before all async calls finish +//or been interrupted (of course, this mechanism will slightly impact efficiency). #ifndef ASCS_DELAY_CLOSE -#define ASCS_DELAY_CLOSE 5 //seconds -#endif -static_assert(ASCS_DELAY_CLOSE > 0, "ASCS_DELAY_CLOSE must be bigger than zero."); +#define ASCS_DELAY_CLOSE 0 //seconds, guarantee 100% safety when reusing or freeing this socket #endif +static_assert(ASCS_DELAY_CLOSE >= 0, "delay close duration must be bigger than or equal to zero."); //full statistic include time consumption, or only numerable informations will be gathered //#define ASCS_FULL_STATISTIC diff --git a/include/ascs/container.h b/include/ascs/container.h index b61ac6a..d21f774 100644 --- a/include/ascs/container.h +++ b/include/ascs/container.h @@ -45,6 +45,7 @@ public: typedef typename _Mybase::const_reverse_iterator const_reverse_iterator; list() : s(0) {} + list(list&& other) : s(0) {swap(other);} void swap(list& other) {impl.swap(other.impl); std::swap(s, other.s);} bool empty() const {return 0 == s;} @@ -133,7 +134,7 @@ private: }; //Container must at least has the following functions: -// Container(size) and Container() constructor +// Container() and Container(size_t) constructor // move constructor // swap // size_approx @@ -156,7 +157,6 @@ public: //not thread-safe void clear() {super(std::move(*this));} - void swap(me& other) {super::swap(other);} bool enqueue_(const T& item) {return this->enqueue(item);} bool enqueue_(T&& item) {return this->enqueue(std::move(item));} @@ -164,7 +164,7 @@ public: }; //Container must at least has the following functions: -// Container() constructor +// Container() and Container(size_t) constructor // size // empty // clear @@ -184,10 +184,6 @@ public: queue() {} queue(size_t size) : super(size) {} - //not thread-safe - void clear() {super::clear();} - void swap(me& other) {super::swap(other);} - bool enqueue(const T& item) {typename Lockable::lock_guard lock(*this); return enqueue_(item);} bool enqueue(T&& item) {typename Lockable::lock_guard lock(*this); return enqueue_(std::move(item));} bool try_dequeue(T& item) {typename Lockable::lock_guard lock(*this); return try_dequeue_(item);} @@ -200,7 +196,7 @@ public: template using non_lock_queue = queue; //totally not thread safe template using lock_queue = queue; -//it's not thread safe for 'other', please note. for this queue, depends on 'Q' +//it's not thread safe for 'other', please note. for 'dest', depends on 'Q' template size_t move_items_in(Q& dest, Q& other, size_t max_size = ASCS_MAX_MSG_NUM) { @@ -225,7 +221,7 @@ size_t move_items_in(Q& dest, Q& other, size_t max_size = ASCS_MAX_MSG_NUM) return num; } -//it's not thread safe for 'other', please note. for this queue, depends on 'Q' +//it's not thread safe for 'other', please note. for 'dest', depends on 'Q' template size_t move_items_in(Q& dest, Q2& other, size_t max_size = ASCS_MAX_MSG_NUM) { @@ -273,7 +269,7 @@ bool splice_helper(_Can& dest_can, _Can& src_can, size_t max_size = ASCS_MAX_MSG return true; } - + } //namespace #endif /* _ASCS_CONTAINER_H_ */ \ No newline at end of file diff --git a/include/ascs/object.h b/include/ascs/object.h index 2baab6a..fb20181 100644 --- a/include/ascs/object.h +++ b/include/ascs/object.h @@ -27,27 +27,23 @@ protected: public: bool stopped() const {return io_service_.stopped();} -#ifdef ASCS_ENHANCED_STABILITY - template - void post(const CallbackHandler& handler) {auto unused(async_call_indicator); io_service_.post([=]() {handler();});} - template - void post(CallbackHandler&& handler) {auto unused(async_call_indicator); io_service_.post([=]() {handler();});} - bool is_async_calling() const {return !async_call_indicator.unique();} - bool is_last_async_call() const {return async_call_indicator.use_count() <= 2;} //can only be called in callbacks +#if 0 == ASCS_DELAY_CLOSE + template void post(F&& handler) {io_service_.post([unused(this->async_call_indicator), handler(std::move(handler))]() {handler();});} + template void post(const F& handler) {io_service_.post([unused(this->async_call_indicator), handler]() {handler();});} + + typedef std::function handler_with_error; + template handler_with_error make_handler_error(F&& handler) const {return [unused(this->async_call_indicator), handler(std::move(handler))](const auto& ec) {handler(ec);};} + template handler_with_error make_handler_error(const F& handler) const {return [unused(this->async_call_indicator), handler](const auto& ec) {handler(ec);};} - template - std::function make_handler_error(CallbackHandler&& handler) const - {auto unused(async_call_indicator); return [=](const auto& ec) {handler(ec);};} - template - std::function make_handler_error(const CallbackHandler& handler) const - {auto unused(async_call_indicator); return [=](const auto& ec) {handler(ec);};} + typedef std::function handler_with_error_size; + template handler_with_error_size make_handler_error_size(F&& handler) const + {return [unused(this->async_call_indicator), handler(std::move(handler))](const auto& ec, auto bytes_transferred) {handler(ec, bytes_transferred);};} + template handler_with_error_size make_handler_error_size(const F& handler) const + {return [unused(this->async_call_indicator), handler](const auto& ec, auto bytes_transferred) {handler(ec, bytes_transferred);};} - template - std::function make_handler_error_size(CallbackHandler&& handler) const - {auto unused(async_call_indicator); return [=](const auto& ec, auto bytes_transferred) {handler(ec, bytes_transferred);};} - template - std::function make_handler_error_size(CallbackHandler& handler) const - {auto unused(async_call_indicator); return [=](const auto& ec, auto bytes_transferred) {handler(ec, bytes_transferred);};} + bool is_async_calling() const {return !async_call_indicator.unique();} + bool is_last_async_call() const {return async_call_indicator.use_count() <= 2;} //can only be called in callbacks + inline void set_async_calling(bool) {} protected: void reset() {async_call_indicator = std::make_shared('\0');} @@ -55,28 +51,26 @@ protected: protected: std::shared_ptr async_call_indicator; #else - template - void post(const CallbackHandler& handler) {io_service_.post(handler);} - template - void post(CallbackHandler&& handler) {io_service_.post(std::move(handler));} - bool is_async_calling() const {return false;} - bool is_last_async_call() const {return true;} - - template - inline F&& make_handler_error(F&& f) const {return std::move(f);} - template - inline const F& make_handler_error(const F& f) const {return f;} - - template - inline F&& make_handler_error_size(F&& f) const {return std::move(f);} - template - inline const F& make_handler_error_size(const F& f) const {return f;} + template void post(F&& handler) {io_service_.post(std::move(handler));} + template void post(const F& handler) {io_service_.post(handler);} + + template inline F&& make_handler_error(F&& f) const {return std::move(f);} + template inline const F& make_handler_error(const F& f) const {return f;} + + template inline F&& make_handler_error_size(F&& f) const {return std::move(f);} + template inline const F& make_handler_error_size(const F& f) const {return f;} + + inline bool is_async_calling() const {return async_calling;} + inline bool is_last_async_call() const {return true;} + inline void set_async_calling(bool value) {async_calling = value;} protected: - void reset() {} -#endif + void reset() {set_async_calling(false);} protected: + bool async_calling; +#endif + asio::io_service& io_service_; }; diff --git a/include/ascs/object_pool.h b/include/ascs/object_pool.h index 85c45cd..8976564 100644 --- a/include/ascs/object_pool.h +++ b/include/ascs/object_pool.h @@ -151,7 +151,7 @@ protected: object_type create_object() {return create_object(sp);} public: - //to configure unordered_set(for example, set factor or reserved size), not locked the mutex, so must be called before service_pump starting up. + //to configure unordered_set(for example, set factor or reserved size), not thread safe, so must be called before service_pump startup. container_type& container() {return object_can;} size_t max_size() const {return max_size_;} @@ -227,7 +227,7 @@ public: std::unique_lock lock(object_can_mutex); for (auto iter = std::begin(object_can); iter != std::end(object_can);) - if (iter->second.unique() && iter->second->obsoleted()) + if (iter->second->obsoleted()) { objects.push_back(std::move(iter->second)); iter = object_can.erase(iter); @@ -259,7 +259,7 @@ public: std::unique_lock lock(invalid_object_can_mutex); for (auto iter = std::begin(invalid_object_can); num > 0 && iter != std::end(invalid_object_can);) - if ((*iter).unique() && (*iter)->obsoleted()) + if ((*iter)->obsoleted()) { --num; ++num_affected; diff --git a/include/ascs/socket.h b/include/ascs/socket.h index 460953e..c101987 100644 --- a/include/ascs/socket.h +++ b/include/ascs/socket.h @@ -55,9 +55,6 @@ protected: sending = paused_sending = false; dispatching = paused_dispatching = congestion_controlling = false; -#ifndef ASCS_ENHANCED_STABILITY - closing = false; -#endif // started_ = false; } @@ -71,9 +68,6 @@ protected: } public: - //please do not change id at runtime via the following function, except this socket is not managed by object_pool, - //it should only be used by object_pool when reusing or creating new socket. - void id(uint_fast64_t id) {assert(!started_); if (started_) unified_out::error_out("id is unchangeable!"); else _id = id;} uint_fast64_t id() const {return _id;} bool is_equal_to(uint_fast64_t id) const {return _id == id;} @@ -82,14 +76,7 @@ public: typename Socket::lowest_layer_type& lowest_layer() {return next_layer().lowest_layer();} const typename Socket::lowest_layer_type& lowest_layer() const {return next_layer().lowest_layer();} - virtual bool obsoleted() - { -#ifndef ASCS_ENHANCED_STABILITY - return started() || closing || this->is_async_calling() ? false : recv_msg_buffer.empty() && recv_msg_buffer.idle(); -#else - return !started() && !this->is_async_calling(); -#endif - } + virtual bool obsoleted() {return !dispatching && !started() && !is_async_calling();} bool started() const {return started_;} void start() @@ -121,7 +108,8 @@ public: void suspend_send_msg(bool suspend) {if (!(paused_sending = suspend)) send_msg();} bool suspend_send_msg() const {return paused_sending;} - void suspend_dispatch_msg(bool suspend) {if (!(paused_dispatching = suspend)) dispatch_msg();} + //for a socket that has been shut down, resuming message dispatching will not take effect for left messages. + void suspend_dispatch_msg(bool suspend) {if (!(paused_dispatching = suspend) && started()) dispatch_msg();} bool suspend_dispatch_msg() const {return paused_dispatching;} void congestion_control(bool enable) {congestion_controlling = enable; unified_out::warning_out("%s congestion control.", enable ? "open" : "close");} @@ -167,10 +155,10 @@ protected: virtual void on_send_error(const asio::error_code& ec) {unified_out::error_out("send msg error (%d %s)", ec.value(), ec.message().data());} //receiving error or peer endpoint quit(false ec means ok) virtual void on_recv_error(const asio::error_code& ec) = 0; - //if ASCS_ENHANCED_STABILITY macro been defined, in this callback, socket guarantee that there's no any async call associated it, - //include user timers(created by set_timer()) and user async calls(started via post()), - //this means you can clean up any resource in this socket except this socket itself, because this socket maybe is being maintained by object_pool. - //if ASCS_ENHANCED_STABILITY macro not defined, socket simply call this callback ASCS_DELAY_CLOSE seconds later after link down, no any guarantees. + //if ASCS_DELAY_CLOSE is equal to zero, in this callback, socket guarantee that there's no any other async call associated it, + // include user timers(created by set_timer()) and user async calls(started via post()), this means you can clean up any resource + // in this socket except this socket itself, because this socket maybe is being maintained by object_pool. + //otherwise (bigger than zero), socket simply call this callback ASCS_DELAY_CLOSE seconds later after link down, no any guarantees. virtual void on_close() {unified_out::info_out("on_close()");} #ifndef ASCS_FORCE_TO_USE_MSG_RECV_BUFFER @@ -209,9 +197,7 @@ protected: { if (is_closable()) { -#ifndef ASCS_ENHANCED_STABILITY - closing = true; -#endif + set_async_calling(true); set_timer(TIMER_DELAY_CLOSE, ASCS_DELAY_CLOSE * 1000 + 50, [this](auto id)->bool {return this->timer_handler(id);}); } } @@ -309,6 +295,11 @@ protected: } private: + //please do not change id at runtime via the following function, except this socket is not managed by object_pool, + //it should only be used by object_pool when reusing or creating new socket. + template friend class object_pool; + void id(uint_fast64_t id) {assert(!started_); if (started_) unified_out::error_out("id is unchangeable!"); else _id = id;} + bool timer_handler(tid id) { switch (id) @@ -329,9 +320,8 @@ private: lowest_layer().close(ec); } on_close(); -#ifndef ASCS_ENHANCED_STABILITY - closing = false; -#endif + set_async_calling(false); + break; default: assert(false); @@ -377,7 +367,7 @@ protected: in_container_type send_msg_buffer; out_container_type recv_msg_buffer; list temp_msg_buffer; - //ascs::tcp::socket will invoke handle_msg() when got some msgs. if these msgs can't be pushed into recv_msg_buffer because of: + //subclass will invoke handle_msg() when got some msgs. if these msgs can't be pushed into recv_msg_buffer because of: // 1. msg dispatching suspended; // 2. congestion control opened; //ascs::socket will delay 50 milliseconds(non-blocking) to invoke handle_msg() again, and now, as you known, temp_msg_buffer is used to hold these msgs temporarily. @@ -386,9 +376,6 @@ protected: std::shared_mutex send_mutex; bool dispatching, paused_dispatching, congestion_controlling; std::shared_mutex dispatch_mutex; -#ifndef ASCS_ENHANCED_STABILITY - bool closing; -#endif bool started_; //has started or not std::shared_mutex start_mutex; diff --git a/include/ascs/ssl/ssl.h b/include/ascs/ssl/ssl.h index 553c5e8..fea028e 100644 --- a/include/ascs/ssl/ssl.h +++ b/include/ascs/ssl/ssl.h @@ -206,17 +206,20 @@ private: if (!ec) { if (this->on_accept(client_ptr)) - client_ptr->next_layer().async_handshake(asio::ssl::stream_base::server, [client_ptr, this](const auto& ec) { - this->on_handshake(ec, client_ptr); - if (!ec && this->add_client(client_ptr)) - client_ptr->start(); - }); + client_ptr->next_layer().async_handshake(asio::ssl::stream_base::server, [client_ptr, this](const auto& ec) {this->handshake_handler(ec, client_ptr);}); start_next_accept(); } else this->stop_listen(); } + + void handshake_handler(const asio::error_code& ec, typename server_base::object_ctype& client_ptr) + { + this->on_handshake(ec, client_ptr); + if (!ec && this->add_client(client_ptr)) + client_ptr->start(); + } }; }} //namespace diff --git a/include/ascs/tcp/socket.h b/include/ascs/tcp/socket.h index ec3816e..0ee2879 100644 --- a/include/ascs/tcp/socket.h +++ b/include/ascs/tcp/socket.h @@ -176,7 +176,6 @@ protected: shutdown_state = shutdown_states::FORCE; this->stop_all_timer(); - this->close(); //must after stop_all_timer(), it's very important this->started_ = false; // reset_state(); @@ -185,6 +184,8 @@ protected: asio::error_code ec; this->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec); } + + this->close(); //call this at the end of 'shutdown', it's very important } private: diff --git a/include/ascs/udp/socket.h b/include/ascs/udp/socket.h index 5dc373c..baceddb 100644 --- a/include/ascs/udp/socket.h +++ b/include/ascs/udp/socket.h @@ -166,7 +166,6 @@ protected: std::unique_lock lock(shutdown_mutex); this->stop_all_timer(); - this->close(); //must after stop_all_timer(), it's very important this->started_ = false; // reset_state(); @@ -176,6 +175,8 @@ protected: this->lowest_layer().shutdown(asio::ip::udp::socket::shutdown_both, ec); this->lowest_layer().close(ec); } + + this->close(); //call this at the end of 'shutdown', it's very important } private: -- GitLab