libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 39affe6c5629b78e418f33787ec7a9556b287832
parent 5b45f52e777fafb65fe9e4a53d202e38e3accdc9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 31 Mar 2013 18:28:43 +0000

adding MHD_run_from_select to API

Diffstat:
MChangeLog | 5+++++
Mdoc/libmicrohttpd.texi | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/daemon/EXPORT.sym | 1+
Msrc/daemon/daemon.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/include/microhttpd.h | 33+++++++++++++++++++++++++++++++++
5 files changed, 146 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +Sun Mar 31 20:27:48 CEST 2013 + Adding new API call 'MHD_run_from_select' to allow programs + running in 'external select mode' to reduce the number of + 'select' calls by a factor of two. -CG + Sun Mar 31 20:03:48 CEST 2013 Performance improvements, updated documentation. Make better use of available memory pool memory for diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi @@ -1095,11 +1095,53 @@ Shutdown an HTTP daemon. Run webserver operations (without blocking unless in client callbacks). This method should be called by clients in combination with @code{MHD_get_fdset()} if the client-controlled @code{select}-method is used. +@cindex select +@cindex poll + +This function will work for external @code{poll} and @code{select} mode. +However, if using external @code{select} mode, you may want to +instead use @code{MHD_run_from_select}, as it is more efficient. + +@table @var +@item daemon +daemon to process connections of +@end table Return @code{MHD_YES} on success, @code{MHD_NO} if this daemon was not started with the right options for this call. @end deftypefun +@deftypefun int MHD_run_from_select (struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set) +Run webserver operations given sets of ready socket handles. +@cindex select + +This method should be called by clients in combination with +@code{MHD_get_fdset} if the client-controlled (external) +select method is used. + +You can use this function instead of @code{MHD_run} if you called +@code{select} on the result from @code{MHD_get_fdset}. File descriptors in +the sets that are not controlled by MHD will be ignored. Calling +this function instead of @code{MHD_run} is more efficient as MHD will +not have to call @code{select} again to determine which operations are +ready. + +@table @var +@item daemon +daemon to process connections of +@item read_fd_set +set of descriptors that must be ready for reading without blocking +@item write_fd_set +set of descriptors that must be ready for writing without blocking +@item except_fd_set +ignored, can be NULL +@end table + +Return @code{MHD_YES} on success, @code{MHD_NO} on serious internal +errors. + +@end deftypefun + @deftypefun void MHD_add_connection (struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen) Add another client connection to the set of connections diff --git a/src/daemon/EXPORT.sym b/src/daemon/EXPORT.sym @@ -4,6 +4,7 @@ MHD_stop_daemon MHD_get_fdset MHD_get_timeout MHD_run +MHD_run_from_select MHD_get_connection_values MHD_set_connection_value MHD_lookup_connection_value diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -1329,7 +1329,66 @@ MHD_get_timeout (struct MHD_Daemon *daemon, /** - * Main select call. + * Run webserver operations. This method should be called by clients + * in combination with MHD_get_fdset if the client-controlled select + * method is used. + * + * You can use this function instead of "MHD_run" if you called + * 'select' on the result from "MHD_get_fdset". File descriptors in + * the sets that are not controlled by MHD will be ignored. Calling + * this function instead of "MHD_run" is more efficient as MHD will + * not have to call 'select' again to determine which operations are + * ready. + * + * @param daemon daemon to run select loop for + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set (not used, can be NULL) + * @return MHD_NO on serious errors, MHD_YES on success + */ +int +MHD_run_from_select (struct MHD_Daemon *daemon, + const fd_set *read_fd_set, + const fd_set *write_fd_set, + const fd_set *except_fd_set) +{ + int ds; + struct MHD_Connection *pos; + struct MHD_Connection *next; + + /* select connection thread handling type */ + if ( (-1 != (ds = daemon->socket_fd)) && + (FD_ISSET (ds, read_fd_set)) ) + MHD_accept_connection (daemon); + if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) + { + /* do not have a thread per connection, process all connections now */ + next = daemon->connections_head; + while (NULL != (pos = next)) + { + next = pos->next; + ds = pos->socket_fd; + if (ds != -1) + { + if ( (FD_ISSET (ds, read_fd_set)) +#if HTTPS_SUPPORT + || (MHD_YES == pos->tls_read_ready) +#endif + ) + pos->read_handler (pos); + if (FD_ISSET (ds, write_fd_set)) + pos->write_handler (pos); + pos->idle_handler (pos); + } + } + } + return MHD_YES; +} + + +/** + * Main internal select call. Will compute select sets, call 'select' + * and then MHD_run_from_select with the result. * * @param daemon daemon to run select loop for * @param may_block YES if blocking, NO if non-blocking @@ -1339,8 +1398,6 @@ static int MHD_select (struct MHD_Daemon *daemon, int may_block) { - struct MHD_Connection *pos; - struct MHD_Connection *next; int num_ready; fd_set rs; fd_set ws; @@ -1349,7 +1406,6 @@ MHD_select (struct MHD_Daemon *daemon, struct timeval timeout; struct timeval *tv; MHD_UNSIGNED_LONG_LONG ltimeout; - int ds; timeout.tv_sec = 0; timeout.tv_usec = 0; @@ -1404,7 +1460,6 @@ MHD_select (struct MHD_Daemon *daemon, tv = &timeout; } num_ready = SELECT (max + 1, &rs, &ws, &es, tv); - if (MHD_YES == daemon->shutdown) return MHD_NO; if (num_ready < 0) @@ -1416,33 +1471,7 @@ MHD_select (struct MHD_Daemon *daemon, #endif return MHD_NO; } - /* select connection thread handling type */ - if ( (-1 != (ds = daemon->socket_fd)) && - (FD_ISSET (ds, &rs)) ) - MHD_accept_connection (daemon); - if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) - { - /* do not have a thread per connection, process all connections now */ - next = daemon->connections_head; - while (NULL != (pos = next)) - { - next = pos->next; - ds = pos->socket_fd; - if (ds != -1) - { - if ( (FD_ISSET (ds, &rs)) -#if HTTPS_SUPPORT - || (MHD_YES == pos->tls_read_ready) -#endif - ) - pos->read_handler (pos); - if (FD_ISSET (ds, &ws)) - pos->write_handler (pos); - pos->idle_handler (pos); - } - } - } - return MHD_YES; + return MHD_run_from_select (daemon, &rs, &ws, &es); } @@ -1647,6 +1676,10 @@ MHD_poll (struct MHD_Daemon *daemon, * by clients in combination with MHD_get_fdset * if the client-controlled select method is used. * + * This function will work for external 'poll' and 'select' mode. + * However, if using external 'select' mode, you may want to + * instead use 'MHD_run_from_select', as it is more efficient. + * * @return MHD_YES on success, MHD_NO if this * daemon was not started with the right * options for this call. diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -1182,6 +1182,14 @@ int MHD_get_timeout (struct MHD_Daemon *daemon, * by clients in combination with MHD_get_fdset * if the client-controlled select method is used. * + * This function is a convenience method, which is useful if the + * fd_sets from "MHD_get_fdset" were not directly passed to 'select'; + * with this function, MHD will internally do the appropriate 'select' + * call itself again. While it is always safe to call 'MHD_run' (in + * external select mode), you should call 'MHD_run_from_select' if + * performance is important (as it saves an expensive call to + * 'select'). + * * @param daemon daemon to run * @return MHD_YES on success, MHD_NO if this * daemon was not started with the right @@ -1191,6 +1199,31 @@ int MHD_run (struct MHD_Daemon *daemon); +/** + * Run webserver operations. This method should be called by clients + * in combination with MHD_get_fdset if the client-controlled select + * method is used. + * + * You can use this function instead of "MHD_run" if you called + * 'select' on the result from "MHD_get_fdset". File descriptors in + * the sets that are not controlled by MHD will be ignored. Calling + * this function instead of "MHD_run" is more efficient as MHD will + * not have to call 'select' again to determine which operations are + * ready. + * + * @param daemon daemon to run select loop for + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set (not used, can be NULL) + * @return MHD_NO on serious errors, MHD_YES on success + */ +int +MHD_run_from_select (struct MHD_Daemon *daemon, + const fd_set *read_fd_set, + const fd_set *write_fd_set, + const fd_set *except_fd_set); + + /* **************** Connection handling functions ***************** */ /**