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()"
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.
......
......@@ -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
......
......@@ -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 */
};
......
......@@ -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"
......
......@@ -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
/*
......
......@@ -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
......
......@@ -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 */
......@@ -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) {
......
......@@ -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
/*
......
......@@ -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;
}
......@@ -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 */
......
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