From 4cbf81da5989b389af0ccfd43e94d4ae38907e5f Mon Sep 17 00:00:00 2001 From: Alexander Alashkin <alexander.alashkin@cesanta.com> Date: Mon, 12 Sep 2016 15:09:35 +0100 Subject: [PATCH] Use user timeout in multithreading polling PUBLISHED_FROM=dbf75bfba087f1b0aa0531e5003ba3e69ed1a6ab --- docs/c-api/net.h/intro.md | 1 + .../net.h/struct_mg_multithreading_opts.md | 12 ++++++++ mongoose.c | 28 +++++++++++++++++-- mongoose.h | 11 ++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 docs/c-api/net.h/struct_mg_multithreading_opts.md diff --git a/docs/c-api/net.h/intro.md b/docs/c-api/net.h/intro.md index d102bac1e..98575483a 100644 --- a/docs/c-api/net.h/intro.md +++ b/docs/c-api/net.h/intro.md @@ -30,6 +30,7 @@ items: - { name: struct_mg_add_sock_opts.md } - { name: struct_mg_bind_opts.md } - { name: struct_mg_connect_opts.md } + - { name: struct_mg_multithreading_opts.md } --- NOTE: Mongoose manager is single threaded. It does not protect diff --git a/docs/c-api/net.h/struct_mg_multithreading_opts.md b/docs/c-api/net.h/struct_mg_multithreading_opts.md new file mode 100644 index 000000000..1e388fe9a --- /dev/null +++ b/docs/c-api/net.h/struct_mg_multithreading_opts.md @@ -0,0 +1,12 @@ +--- +title: "struct mg_multithreading_opts" +decl_name: "struct mg_multithreading_opts" +symbol_kind: "struct" +signature: | + struct mg_multithreading_opts { + int poll_timeout; /* Polling interval */ + }; +--- + +Optional parameters for mg_enable_multithreading_opt() + diff --git a/mongoose.c b/mongoose.c index 64f07c3c2..5e9377efb 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3456,13 +3456,15 @@ static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p); static void *per_connection_thread_function(void *param) { struct mg_connection *c = (struct mg_connection *) param; struct mg_mgr m; + /* mgr_data can be used subsequently, store its value */ + int poll_timeout = (intptr_t) c->mgr_data; mg_mgr_init(&m, NULL); mg_add_conn(&m, c); mg_call(c, NULL, MG_EV_ACCEPT, &c->sa); while (m.active_connections != NULL) { - mg_mgr_poll(&m, 1000); + mg_mgr_poll(&m, poll_timeout ? poll_timeout : 1000); } mg_mgr_free(&m); @@ -3496,7 +3498,7 @@ static void spawn_handling_thread(struct mg_connection *nc) { struct mg_mgr dummy; sock_t sp[2]; struct mg_connection *c[2]; - + int poll_timeout; /* * Create a socket pair, and wrap each socket into the connection with * dummy event manager. @@ -3507,6 +3509,9 @@ static void spawn_handling_thread(struct mg_connection *nc) { c[0] = mg_add_sock(&dummy, sp[0], forwarder_ev_handler); c[1] = mg_add_sock(&dummy, sp[1], nc->listener->priv_1.f); + /* link_conns replaces priv_2, storing its value */ + poll_timeout = (intptr_t) nc->priv_2; + /* Interlink client connection with c[0] */ link_conns(c[0], nc); @@ -3526,6 +3531,9 @@ static void spawn_handling_thread(struct mg_connection *nc) { c[1]->sa = nc->sa; c[1]->flags = nc->flags; + /* priv_2 is used, so, put timeout to mgr_data */ + c[1]->mgr_data = (void *) (intptr_t) poll_timeout; + mg_start_thread(per_connection_thread_function, c[1]); } @@ -3537,11 +3545,25 @@ static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p) { } } -void mg_enable_multithreading(struct mg_connection *nc) { +void mg_enable_multithreading_opt(struct mg_connection *nc, + struct mg_multithreading_opts opts) { /* Wrap user event handler into our multithreaded_ev_handler */ nc->priv_1.f = nc->handler; + /* + * We put timeout to `priv_2` member of the main + * (listening) connection, mt is not enabled yet, + * and this member is not used + */ + nc->priv_2 = (void *) (intptr_t) opts.poll_timeout; nc->handler = multithreaded_ev_handler; } + +void mg_enable_multithreading(struct mg_connection *nc) { + struct mg_multithreading_opts opts; + memset(&opts, 0, sizeof(opts)); + mg_enable_multithreading_opt(nc, opts); +} + #endif #ifdef MG_MODULE_LINES #line 1 "./src/uri.c" diff --git a/mongoose.h b/mongoose.h index c68deae3f..069e6d323 100644 --- a/mongoose.h +++ b/mongoose.h @@ -189,6 +189,7 @@ #endif #if defined(_MSC_VER) && _MSC_VER <= 1200 typedef unsigned long uintptr_t; +typedef long intptr_t; #endif typedef int socklen_t; #if _MSC_VER >= 1700 @@ -287,6 +288,7 @@ typedef struct _stati64 cs_stat_t; #include <errno.h> #include <fcntl.h> #include <inttypes.h> +#include <stdint.h> #include <limits.h> #include <math.h> #include <netdb.h> @@ -1583,6 +1585,13 @@ int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); */ int mg_check_ip_acl(const char *acl, uint32_t remote_ip); +/* + * Optional parameters for mg_enable_multithreading_opt() + */ +struct mg_multithreading_opts { + int poll_timeout; /* Polling interval */ +}; + /* * Enables multi-threaded handling for the given listening connection `nc`. * For each accepted connection, Mongoose will create a separate thread @@ -1591,6 +1600,8 @@ int mg_check_ip_acl(const char *acl, uint32_t remote_ip); * other connections. */ void mg_enable_multithreading(struct mg_connection *nc); +void mg_enable_multithreading_opt(struct mg_connection *nc, + struct mg_multithreading_opts opts); #ifdef MG_ENABLE_JAVASCRIPT /* -- GitLab