From 421e099f2b8ae66741a07607091206f542340eb5 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov <rojer@cesanta.com> Date: Mon, 9 Jul 2018 13:16:58 +0300 Subject: [PATCH] Refactor mg polling * Change return type of mg_mgr_poll to return number of events * Add mg_mgr_min_timer * Refactor main poll loop to remove LwIP-specific stuff CL: Refactor mg polling PUBLISHED_FROM=dc94618b32fa3c84a2f053bd04d134297780ec82 --- docs/c-api/mg_net.h/mg_mgr_free.md | 2 +- docs/c-api/mg_net.h/mg_mgr_poll.md | 4 +- docs/c-api/mg_net.h/struct_mg_mgr.md | 1 + mongoose.c | 60 +++++++--------------- mongoose.h | 14 +++-- src/common/platforms/lwip/mg_lwip.h | 1 - src/common/platforms/lwip/mg_lwip_ev_mgr.c | 32 ------------ src/mg_net.c | 16 +++--- src/mg_net.h | 7 +-- src/mg_net_if.c | 12 +++++ src/mg_net_if.h | 6 +++ 11 files changed, 60 insertions(+), 95 deletions(-) diff --git a/docs/c-api/mg_net.h/mg_mgr_free.md b/docs/c-api/mg_net.h/mg_mgr_free.md index d2df34e4c..60ad75bdc 100644 --- a/docs/c-api/mg_net.h/mg_mgr_free.md +++ b/docs/c-api/mg_net.h/mg_mgr_free.md @@ -3,7 +3,7 @@ title: "mg_mgr_free()" decl_name: "mg_mgr_free" symbol_kind: "func" signature: | - void mg_mgr_free(struct mg_mgr *); + void mg_mgr_free(struct mg_mgr *mgr); --- De-initialises Mongoose manager. diff --git a/docs/c-api/mg_net.h/mg_mgr_poll.md b/docs/c-api/mg_net.h/mg_mgr_poll.md index b70c31b6d..ef48a1908 100644 --- a/docs/c-api/mg_net.h/mg_mgr_poll.md +++ b/docs/c-api/mg_net.h/mg_mgr_poll.md @@ -3,11 +3,11 @@ title: "mg_mgr_poll()" decl_name: "mg_mgr_poll" symbol_kind: "func" signature: | - time_t mg_mgr_poll(struct mg_mgr *, int milli); + int mg_mgr_poll(struct mg_mgr *mgr, int milli); --- This function performs the actual IO and must be called in a loop -(an event loop). It returns the current timestamp. +(an event loop). It returns number of user events generated (except POLLs). `milli` is the maximum number of milliseconds to sleep. `mg_mgr_poll()` checks all connections for IO readiness. If at least one of the connections is IO-ready, `mg_mgr_poll()` triggers the respective diff --git a/docs/c-api/mg_net.h/struct_mg_mgr.md b/docs/c-api/mg_net.h/struct_mg_mgr.md index d33727c38..44efa5fdf 100644 --- a/docs/c-api/mg_net.h/struct_mg_mgr.md +++ b/docs/c-api/mg_net.h/struct_mg_mgr.md @@ -13,6 +13,7 @@ signature: | #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; diff --git a/mongoose.c b/mongoose.c index d09345c5e..7b0170c2b 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2408,6 +2408,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); } } + if (ev != MG_EV_POLL) nc->mgr->num_calls++; if (ev != MG_EV_POLL) { DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, ev_handler == nc->handler ? "user" : "proto", nc->flags, @@ -2585,19 +2586,14 @@ void mg_mgr_free(struct mg_mgr *m) { MG_FREE((char *) m->nameserver); } -time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { - int i; - time_t now = 0; /* oh GCC, seriously ? */ - - if (m->num_ifaces == 0) { - LOG(LL_ERROR, ("cannot poll: no interfaces")); - return 0; - } +int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { + int i, num_calls_before = m->num_calls; for (i = 0; i < m->num_ifaces; i++) { - now = m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms); + m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms); } - return now; + + return (m->num_calls - num_calls_before); } int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) { @@ -3585,6 +3581,18 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr, } return NULL; } + +double mg_mgr_min_timer(const struct mg_mgr *mgr) { + double min_timer = 0; + struct mg_connection *nc; + for (nc = mgr->active_connections; nc != NULL; nc = nc->next) { + if (nc->ev_timer_time <= 0) continue; + if (min_timer == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + } + return min_timer; +} #ifdef MG_MODULE_LINES #line 1 "mongoose/src/mg_net_if_socket.c" #endif @@ -15716,38 +15724,6 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { return now; } -uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { - struct mg_connection *nc; - double now; - double min_timer = 0; - int num_timers = 0; - mg_ev_mgr_lwip_process_signals(mgr); - for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { - struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; - if (nc->ev_timer_time > 0) { - if (num_timers == 0 || nc->ev_timer_time < min_timer) { - min_timer = nc->ev_timer_time; - } - num_timers++; - } - /* We want and can send data, request a poll immediately. */ - if (nc->sock != INVALID_SOCKET && mg_lwip_if_can_send(nc, cs)) { - return 0; - } - } - uint32_t timeout_ms = ~0; - now = mg_time(); - if (num_timers > 0) { - /* If we have a timer that is past due, do a poll ASAP. */ - if (min_timer < now) return 0; - double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; - if (timer_timeout_ms < timeout_ms) { - timeout_ms = timer_timeout_ms; - } - } - return timeout_ms; -} - #endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */ #ifdef MG_MODULE_LINES #line 1 "common/platforms/wince/wince_libc.c" diff --git a/mongoose.h b/mongoose.h index 2667c7590..7c179d692 100644 --- a/mongoose.h +++ b/mongoose.h @@ -2030,7 +2030,6 @@ typedef int sock_t; #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL struct mg_mgr; struct mg_connection; -uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr); void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle, int interval, int count); #endif @@ -3718,6 +3717,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, /* Deliver a POLL event to the connection. */ int mg_if_poll(struct mg_connection *nc, double now); +/* + * Return minimal timer value amoung connections in the manager. + * Returns 0 if there aren't any timers. + */ +double mg_mgr_min_timer(const struct mg_mgr *mgr); + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -3875,6 +3880,7 @@ struct mg_mgr { #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; @@ -3987,17 +3993,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, * * Closes and deallocates all active connections. */ -void mg_mgr_free(struct mg_mgr *); +void mg_mgr_free(struct mg_mgr *mgr); /* * This function performs the actual IO and must be called in a loop - * (an event loop). It returns the current timestamp. + * (an event loop). It returns number of user events generated (except POLLs). * `milli` is the maximum number of milliseconds to sleep. * `mg_mgr_poll()` checks all connections for IO readiness. If at least one * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective * event handlers and returns. */ -time_t mg_mgr_poll(struct mg_mgr *, int milli); +int mg_mgr_poll(struct mg_mgr *mgr, int milli); #if MG_ENABLE_BROADCAST /* diff --git a/src/common/platforms/lwip/mg_lwip.h b/src/common/platforms/lwip/mg_lwip.h index c0d4081e8..c15e2ee2d 100644 --- a/src/common/platforms/lwip/mg_lwip.h +++ b/src/common/platforms/lwip/mg_lwip.h @@ -66,7 +66,6 @@ typedef int sock_t; #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL struct mg_mgr; struct mg_connection; -uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr); void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle, int interval, int count); #endif diff --git a/src/common/platforms/lwip/mg_lwip_ev_mgr.c b/src/common/platforms/lwip/mg_lwip_ev_mgr.c index 39937fc91..b495464e9 100644 --- a/src/common/platforms/lwip/mg_lwip_ev_mgr.c +++ b/src/common/platforms/lwip/mg_lwip_ev_mgr.c @@ -167,36 +167,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { return now; } -uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { - struct mg_connection *nc; - double now; - double min_timer = 0; - int num_timers = 0; - mg_ev_mgr_lwip_process_signals(mgr); - for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) { - struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; - if (nc->ev_timer_time > 0) { - if (num_timers == 0 || nc->ev_timer_time < min_timer) { - min_timer = nc->ev_timer_time; - } - num_timers++; - } - /* We want and can send data, request a poll immediately. */ - if (nc->sock != INVALID_SOCKET && mg_lwip_if_can_send(nc, cs)) { - return 0; - } - } - uint32_t timeout_ms = ~0; - now = mg_time(); - if (num_timers > 0) { - /* If we have a timer that is past due, do a poll ASAP. */ - if (min_timer < now) return 0; - double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */; - if (timer_timeout_ms < timeout_ms) { - timeout_ms = timer_timeout_ms; - } - } - return timeout_ms; -} - #endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */ diff --git a/src/mg_net.c b/src/mg_net.c index 5c9614091..3862fa892 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -99,6 +99,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); } } + if (ev != MG_EV_POLL) nc->mgr->num_calls++; if (ev != MG_EV_POLL) { DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, ev_handler == nc->handler ? "user" : "proto", nc->flags, @@ -276,19 +277,14 @@ void mg_mgr_free(struct mg_mgr *m) { MG_FREE((char *) m->nameserver); } -time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { - int i; - time_t now = 0; /* oh GCC, seriously ? */ - - if (m->num_ifaces == 0) { - LOG(LL_ERROR, ("cannot poll: no interfaces")); - return 0; - } +int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { + int i, num_calls_before = m->num_calls; for (i = 0; i < m->num_ifaces; i++) { - now = m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms); + m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms); } - return now; + + return (m->num_calls - num_calls_before); } int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) { diff --git a/src/mg_net.h b/src/mg_net.h index 90b42b47a..d854e770a 100644 --- a/src/mg_net.h +++ b/src/mg_net.h @@ -89,6 +89,7 @@ struct mg_mgr { #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; @@ -201,17 +202,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, * * Closes and deallocates all active connections. */ -void mg_mgr_free(struct mg_mgr *); +void mg_mgr_free(struct mg_mgr *mgr); /* * This function performs the actual IO and must be called in a loop - * (an event loop). It returns the current timestamp. + * (an event loop). It returns number of user events generated (except POLLs). * `milli` is the maximum number of milliseconds to sleep. * `mg_mgr_poll()` checks all connections for IO readiness. If at least one * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective * event handlers and returns. */ -time_t mg_mgr_poll(struct mg_mgr *, int milli); +int mg_mgr_poll(struct mg_mgr *mgr, int milli); #if MG_ENABLE_BROADCAST /* diff --git a/src/mg_net_if.c b/src/mg_net_if.c index 2a93dcfd4..c91feb996 100644 --- a/src/mg_net_if.c +++ b/src/mg_net_if.c @@ -39,3 +39,15 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr, } return NULL; } + +double mg_mgr_min_timer(const struct mg_mgr *mgr) { + double min_timer = 0; + struct mg_connection *nc; + for (nc = mgr->active_connections; nc != NULL; nc = nc->next) { + if (nc->ev_timer_time <= 0) continue; + if (min_timer == 0 || nc->ev_timer_time < min_timer) { + min_timer = nc->ev_timer_time; + } + } + return min_timer; +} diff --git a/src/mg_net_if.h b/src/mg_net_if.h index cba58fb95..1239d54a0 100644 --- a/src/mg_net_if.h +++ b/src/mg_net_if.h @@ -118,6 +118,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, /* Deliver a POLL event to the connection. */ int mg_if_poll(struct mg_connection *nc, double now); +/* + * Return minimal timer value amoung connections in the manager. + * Returns 0 if there aren't any timers. + */ +double mg_mgr_min_timer(const struct mg_mgr *mgr); + #ifdef __cplusplus } #endif /* __cplusplus */ -- GitLab