Commit 707b9ed2 authored by Alexander Alashkin's avatar Alexander Alashkin Committed by Cesanta Bot

Remove mg_enable_multithreading. Close cesanta/dev#6511

PUBLISHED_FROM=7864ffa26cb553f5d4a93248f67c288327ec23b0
parent cd6b846e
......@@ -12,7 +12,6 @@ items:
- { name: mg_connect.md }
- { name: mg_connect_opt.md }
- { name: mg_enable_javascript.md }
- { name: mg_enable_multithreading.md }
- { name: mg_mgr_free.md }
- { name: mg_mgr_init.md }
- { name: mg_mgr_init_opt.md }
......@@ -33,7 +32,6 @@ items:
- { name: struct_mg_connection.md }
- { name: struct_mg_mgr.md }
- { name: struct_mg_mgr_init_opts.md }
- { name: struct_mg_multithreading_opts.md }
---
NOTE: Mongoose manager is single threaded. It does not protect
......
---
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.
*/
mg_event_handler_t f;
} priv_1; /* Used by mg_enable_multithreading() */
void *priv_2; /* Used by mg_enable_multithreading() */
} priv_1;
void *priv_2;
void *mgr_data; /* Implementation-specific event manager's data. */
struct mg_iface *iface;
unsigned long flags;
......
---
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()
PROG = multithreaded_restful_server
MODULE_CFLAGS = -DMG_ENABLE_THREADS
SSL_LIB=openssl
include ../examples.mk
// 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;
}
......@@ -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 */
#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"
#endif
/*
......
......@@ -3281,8 +3281,8 @@ struct mg_connection {
* void pointers, since some archs might have fat pointers for functions.
*/
mg_event_handler_t f;
} priv_1; /* Used by mg_enable_multithreading() */
void *priv_2; /* Used by mg_enable_multithreading() */
} priv_1;
void *priv_2;
void *mgr_data; /* Implementation-specific event manager's data. */
struct mg_iface *iface;
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);
/*
* 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
/*
* Enables server-side JavaScript scripting.
......
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