mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-08 01:42:52 +08:00
Remove mg_enable_multithreading. Close cesanta/dev#6511
PUBLISHED_FROM=7864ffa26cb553f5d4a93248f67c288327ec23b0
This commit is contained in:
parent
cd6b846e22
commit
707b9ed2d6
@ -12,7 +12,6 @@ items:
|
|||||||
- { name: mg_connect.md }
|
- { name: mg_connect.md }
|
||||||
- { name: mg_connect_opt.md }
|
- { name: mg_connect_opt.md }
|
||||||
- { name: mg_enable_javascript.md }
|
- { name: mg_enable_javascript.md }
|
||||||
- { name: mg_enable_multithreading.md }
|
|
||||||
- { name: mg_mgr_free.md }
|
- { name: mg_mgr_free.md }
|
||||||
- { name: mg_mgr_init.md }
|
- { name: mg_mgr_init.md }
|
||||||
- { name: mg_mgr_init_opt.md }
|
- { name: mg_mgr_init_opt.md }
|
||||||
@ -33,7 +32,6 @@ items:
|
|||||||
- { name: struct_mg_connection.md }
|
- { name: struct_mg_connection.md }
|
||||||
- { name: struct_mg_mgr.md }
|
- { name: struct_mg_mgr.md }
|
||||||
- { name: struct_mg_mgr_init_opts.md }
|
- { name: struct_mg_mgr_init_opts.md }
|
||||||
- { name: struct_mg_multithreading_opts.md }
|
|
||||||
---
|
---
|
||||||
|
|
||||||
NOTE: Mongoose manager is single threaded. It does not protect
|
NOTE: Mongoose manager is single threaded. It does not protect
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: "mg_enable_multithreading()"
|
|
||||||
decl_name: "mg_enable_multithreading"
|
|
||||||
symbol_kind: "func"
|
|
||||||
signature: |
|
|
||||||
void mg_enable_multithreading(struct mg_connection *nc);
|
|
||||||
---
|
|
||||||
|
|
||||||
Enables multi-threaded handling for the given listening connection `nc`.
|
|
||||||
For each accepted connection, Mongoose will create a separate thread
|
|
||||||
and run an event handler in that thread. Thus, if an event handler is doing
|
|
||||||
a blocking call or some long computation, it will not slow down
|
|
||||||
other connections.
|
|
||||||
|
|
@ -31,8 +31,8 @@ signature: |
|
|||||||
* void pointers, since some archs might have fat pointers for functions.
|
* void pointers, since some archs might have fat pointers for functions.
|
||||||
*/
|
*/
|
||||||
mg_event_handler_t f;
|
mg_event_handler_t f;
|
||||||
} priv_1; /* Used by mg_enable_multithreading() */
|
} priv_1;
|
||||||
void *priv_2; /* Used by mg_enable_multithreading() */
|
void *priv_2;
|
||||||
void *mgr_data; /* Implementation-specific event manager's data. */
|
void *mgr_data; /* Implementation-specific event manager's data. */
|
||||||
struct mg_iface *iface;
|
struct mg_iface *iface;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
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()
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
PROG = multithreaded_restful_server
|
|
||||||
MODULE_CFLAGS = -DMG_ENABLE_THREADS
|
|
||||||
SSL_LIB=openssl
|
|
||||||
include ../examples.mk
|
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2015 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
// This example shows how to handle long, blocking requests by
|
|
||||||
// handing off computation to different threads. Here, each
|
|
||||||
// request spawns a new thread. In a production scenario, a thread
|
|
||||||
// pools can be used for efficiency, if required.
|
|
||||||
// Long computation is simulated by sleeping for a random interval.
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
static const char *s_http_port = "8000";
|
|
||||||
|
|
||||||
static void ev_handler(struct mg_connection *c, int ev, void *p) {
|
|
||||||
if (ev == MG_EV_HTTP_REQUEST) {
|
|
||||||
struct http_message *hm = (struct http_message *) p;
|
|
||||||
char reply[100];
|
|
||||||
|
|
||||||
/* Simulate long calculation */
|
|
||||||
sleep(3);
|
|
||||||
|
|
||||||
/* Send the reply */
|
|
||||||
snprintf(reply, sizeof(reply), "{ \"uri\": \"%.*s\" }\n", (int) hm->uri.len,
|
|
||||||
hm->uri.p);
|
|
||||||
mg_printf(c,
|
|
||||||
"HTTP/1.1 200 OK\r\n"
|
|
||||||
"Content-Type: application/json\r\n"
|
|
||||||
"Content-Length: %d\r\n"
|
|
||||||
"\r\n"
|
|
||||||
"%s",
|
|
||||||
(int) strlen(reply), reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
struct mg_mgr mgr;
|
|
||||||
struct mg_connection *nc;
|
|
||||||
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
|
||||||
nc = mg_bind(&mgr, s_http_port, ev_handler);
|
|
||||||
mg_set_protocol_http_websocket(nc);
|
|
||||||
|
|
||||||
/* For each new connection, execute ev_handler in a separate thread */
|
|
||||||
mg_enable_multithreading(nc);
|
|
||||||
|
|
||||||
printf("Starting multi-threaded server on port %s\n", s_http_port);
|
|
||||||
for (;;) {
|
|
||||||
mg_mgr_poll(&mgr, 3000);
|
|
||||||
}
|
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
133
mongoose.c
133
mongoose.c
@ -4627,139 +4627,6 @@ int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) {
|
|||||||
|
|
||||||
#endif /* MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS */
|
#endif /* MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS */
|
||||||
#ifdef MG_MODULE_LINES
|
#ifdef MG_MODULE_LINES
|
||||||
#line 1 "mongoose/src/multithreading.c"
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Amalgamated: #include "mongoose/src/internal.h" */
|
|
||||||
/* Amalgamated: #include "mongoose/src/util.h" */
|
|
||||||
|
|
||||||
#if MG_ENABLE_THREADS
|
|
||||||
|
|
||||||
static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This thread function executes user event handler.
|
|
||||||
* It runs an event manager that has only one connection, until that
|
|
||||||
* connection is alive.
|
|
||||||
*/
|
|
||||||
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, poll_timeout ? poll_timeout : 1000);
|
|
||||||
}
|
|
||||||
mg_mgr_free(&m);
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void link_conns(struct mg_connection *c1, struct mg_connection *c2) {
|
|
||||||
c1->priv_2 = c2;
|
|
||||||
c2->priv_2 = c1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unlink_conns(struct mg_connection *c) {
|
|
||||||
struct mg_connection *peer = (struct mg_connection *) c->priv_2;
|
|
||||||
if (peer != NULL) {
|
|
||||||
peer->flags |= MG_F_SEND_AND_CLOSE;
|
|
||||||
peer->priv_2 = NULL;
|
|
||||||
}
|
|
||||||
c->priv_2 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void forwarder_ev_handler(struct mg_connection *c, int ev, void *p) {
|
|
||||||
(void) p;
|
|
||||||
if (ev == MG_EV_RECV && c->priv_2) {
|
|
||||||
mg_forward(c, (struct mg_connection *) c->priv_2);
|
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
|
||||||
unlink_conns(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
* c[0] stays in this thread, c[1] goes to another thread.
|
|
||||||
*/
|
|
||||||
mg_mgr_init(&dummy, NULL);
|
|
||||||
mg_socketpair(sp, SOCK_STREAM);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Switch c[0] manager from the dummy one to the real one. c[1] manager
|
|
||||||
* will be set in another thread, allocated on stack of that thread.
|
|
||||||
*/
|
|
||||||
mg_add_conn(nc->mgr, c[0]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dress c[1] as nc.
|
|
||||||
* TODO(lsm): code in accept_conn() looks similar. Refactor.
|
|
||||||
*/
|
|
||||||
c[1]->listener = nc->listener;
|
|
||||||
c[1]->proto_handler = nc->proto_handler;
|
|
||||||
c[1]->user_data = nc->user_data;
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void multithreaded_ev_handler(struct mg_connection *c, int ev, void *p) {
|
|
||||||
(void) p;
|
|
||||||
if (ev == MG_EV_ACCEPT) {
|
|
||||||
spawn_handling_thread(c);
|
|
||||||
c->handler = forwarder_ev_handler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 "mongoose/src/uri.c"
|
#line 1 "mongoose/src/uri.c"
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
|
22
mongoose.h
22
mongoose.h
@ -3281,8 +3281,8 @@ struct mg_connection {
|
|||||||
* void pointers, since some archs might have fat pointers for functions.
|
* void pointers, since some archs might have fat pointers for functions.
|
||||||
*/
|
*/
|
||||||
mg_event_handler_t f;
|
mg_event_handler_t f;
|
||||||
} priv_1; /* Used by mg_enable_multithreading() */
|
} priv_1;
|
||||||
void *priv_2; /* Used by mg_enable_multithreading() */
|
void *priv_2;
|
||||||
void *mgr_data; /* Implementation-specific event manager's data. */
|
void *mgr_data; /* Implementation-specific event manager's data. */
|
||||||
struct mg_iface *iface;
|
struct mg_iface *iface;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -3692,24 +3692,6 @@ 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);
|
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
|
|
||||||
* and run an event handler in that thread. Thus, if an event handler is doing
|
|
||||||
* a blocking call or some long computation, it will not slow down
|
|
||||||
* other connections.
|
|
||||||
*/
|
|
||||||
void mg_enable_multithreading(struct mg_connection *nc);
|
|
||||||
void mg_enable_multithreading_opt(struct mg_connection *nc,
|
|
||||||
struct mg_multithreading_opts opts);
|
|
||||||
|
|
||||||
#if MG_ENABLE_JAVASCRIPT
|
#if MG_ENABLE_JAVASCRIPT
|
||||||
/*
|
/*
|
||||||
* Enables server-side JavaScript scripting.
|
* Enables server-side JavaScript scripting.
|
||||||
|
Loading…
Reference in New Issue
Block a user