Skip to content

Commit

Permalink
Refactor mg polling
Browse files Browse the repository at this point in the history
 * 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
  • Loading branch information
Deomid Ryabkov authored and cesantabot committed Sep 6, 2018
1 parent 955d4a3 commit 421e099
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 95 deletions.
2 changes: 1 addition & 1 deletion docs/c-api/mg_net.h/mg_mgr_free.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions docs/c-api/mg_net.h/mg_mgr_poll.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/c-api/mg_net.h/struct_mg_mgr.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};
Expand Down
60 changes: 18 additions & 42 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down
14 changes: 10 additions & 4 deletions mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
};
Expand Down Expand Up @@ -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
/*
Expand Down
1 change: 0 additions & 1 deletion src/common/platforms/lwip/mg_lwip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 0 additions & 32 deletions src/common/platforms/lwip/mg_lwip_ev_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
16 changes: 6 additions & 10 deletions src/mg_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 4 additions & 3 deletions src/mg_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};
Expand Down Expand Up @@ -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
/*
Expand Down
12 changes: 12 additions & 0 deletions src/mg_net_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 6 additions & 0 deletions src/mg_net_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 421e099

Please sign in to comment.