Commit 421e099f authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by Cesanta Bot

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
parent 955d4a31
...@@ -3,7 +3,7 @@ title: "mg_mgr_free()" ...@@ -3,7 +3,7 @@ title: "mg_mgr_free()"
decl_name: "mg_mgr_free" decl_name: "mg_mgr_free"
symbol_kind: "func" symbol_kind: "func"
signature: | signature: |
void mg_mgr_free(struct mg_mgr *); void mg_mgr_free(struct mg_mgr *mgr);
--- ---
De-initialises Mongoose manager. De-initialises Mongoose manager.
......
...@@ -3,11 +3,11 @@ title: "mg_mgr_poll()" ...@@ -3,11 +3,11 @@ title: "mg_mgr_poll()"
decl_name: "mg_mgr_poll" decl_name: "mg_mgr_poll"
symbol_kind: "func" symbol_kind: "func"
signature: | 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 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. `milli` is the maximum number of milliseconds to sleep.
`mg_mgr_poll()` checks all connections for IO readiness. If at least one `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 of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
......
...@@ -13,6 +13,7 @@ signature: | ...@@ -13,6 +13,7 @@ signature: |
#endif #endif
void *user_data; /* User data */ void *user_data; /* User data */
int num_ifaces; int num_ifaces;
int num_calls;
struct mg_iface **ifaces; /* network interfaces */ struct mg_iface **ifaces; /* network interfaces */
const char *nameserver; /* DNS server to use */ const char *nameserver; /* DNS server to use */
}; };
......
...@@ -2408,6 +2408,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, ...@@ -2408,6 +2408,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
(nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK);
} }
} }
if (ev != MG_EV_POLL) nc->mgr->num_calls++;
if (ev != MG_EV_POLL) { if (ev != MG_EV_POLL) {
DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
ev_handler == nc->handler ? "user" : "proto", nc->flags, ev_handler == nc->handler ? "user" : "proto", nc->flags,
...@@ -2585,19 +2586,14 @@ void mg_mgr_free(struct mg_mgr *m) { ...@@ -2585,19 +2586,14 @@ void mg_mgr_free(struct mg_mgr *m) {
MG_FREE((char *) m->nameserver); MG_FREE((char *) m->nameserver);
} }
time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) {
int i; int i, num_calls_before = m->num_calls;
time_t now = 0; /* oh GCC, seriously ? */
if (m->num_ifaces == 0) {
LOG(LL_ERROR, ("cannot poll: no interfaces"));
return 0;
}
for (i = 0; i < m->num_ifaces; i++) { 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) { 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, ...@@ -3585,6 +3581,18 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr,
} }
return NULL; 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 #ifdef MG_MODULE_LINES
#line 1 "mongoose/src/mg_net_if_socket.c" #line 1 "mongoose/src/mg_net_if_socket.c"
#endif #endif
...@@ -15716,38 +15724,6 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { ...@@ -15716,38 +15724,6 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
return now; 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 */ #endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
#ifdef MG_MODULE_LINES #ifdef MG_MODULE_LINES
#line 1 "common/platforms/wince/wince_libc.c" #line 1 "common/platforms/wince/wince_libc.c"
......
...@@ -2030,7 +2030,6 @@ typedef int sock_t; ...@@ -2030,7 +2030,6 @@ typedef int sock_t;
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
struct mg_mgr; struct mg_mgr;
struct mg_connection; 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, void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
int interval, int count); int interval, int count);
#endif #endif
...@@ -3718,6 +3717,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, ...@@ -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. */ /* Deliver a POLL event to the connection. */
int mg_if_poll(struct mg_connection *nc, double now); 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 #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
...@@ -3875,6 +3880,7 @@ struct mg_mgr { ...@@ -3875,6 +3880,7 @@ struct mg_mgr {
#endif #endif
void *user_data; /* User data */ void *user_data; /* User data */
int num_ifaces; int num_ifaces;
int num_calls;
struct mg_iface **ifaces; /* network interfaces */ struct mg_iface **ifaces; /* network interfaces */
const char *nameserver; /* DNS server to use */ const char *nameserver; /* DNS server to use */
}; };
...@@ -3987,17 +3993,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, ...@@ -3987,17 +3993,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data,
* *
* Closes and deallocates all active connections. * 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 * 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. * `milli` is the maximum number of milliseconds to sleep.
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one * `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 * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
* event handlers and returns. * 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 #if MG_ENABLE_BROADCAST
/* /*
......
...@@ -66,7 +66,6 @@ typedef int sock_t; ...@@ -66,7 +66,6 @@ typedef int sock_t;
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
struct mg_mgr; struct mg_mgr;
struct mg_connection; 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, void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
int interval, int count); int interval, int count);
#endif #endif
......
...@@ -167,36 +167,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { ...@@ -167,36 +167,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
return now; 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 */ #endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
...@@ -99,6 +99,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, ...@@ -99,6 +99,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
(nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK);
} }
} }
if (ev != MG_EV_POLL) nc->mgr->num_calls++;
if (ev != MG_EV_POLL) { if (ev != MG_EV_POLL) {
DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
ev_handler == nc->handler ? "user" : "proto", nc->flags, ev_handler == nc->handler ? "user" : "proto", nc->flags,
...@@ -276,19 +277,14 @@ void mg_mgr_free(struct mg_mgr *m) { ...@@ -276,19 +277,14 @@ void mg_mgr_free(struct mg_mgr *m) {
MG_FREE((char *) m->nameserver); MG_FREE((char *) m->nameserver);
} }
time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) {
int i; int i, num_calls_before = m->num_calls;
time_t now = 0; /* oh GCC, seriously ? */
if (m->num_ifaces == 0) {
LOG(LL_ERROR, ("cannot poll: no interfaces"));
return 0;
}
for (i = 0; i < m->num_ifaces; i++) { 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) { int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) {
......
...@@ -89,6 +89,7 @@ struct mg_mgr { ...@@ -89,6 +89,7 @@ struct mg_mgr {
#endif #endif
void *user_data; /* User data */ void *user_data; /* User data */
int num_ifaces; int num_ifaces;
int num_calls;
struct mg_iface **ifaces; /* network interfaces */ struct mg_iface **ifaces; /* network interfaces */
const char *nameserver; /* DNS server to use */ const char *nameserver; /* DNS server to use */
}; };
...@@ -201,17 +202,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, ...@@ -201,17 +202,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data,
* *
* Closes and deallocates all active connections. * 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 * 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. * `milli` is the maximum number of milliseconds to sleep.
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one * `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 * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
* event handlers and returns. * 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 #if MG_ENABLE_BROADCAST
/* /*
......
...@@ -39,3 +39,15 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr, ...@@ -39,3 +39,15 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr,
} }
return NULL; 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;
}
...@@ -118,6 +118,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, ...@@ -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. */ /* Deliver a POLL event to the connection. */
int mg_if_poll(struct mg_connection *nc, double now); 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 #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment