diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-03-31 18:28:43 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-03-31 18:28:43 +0000 |
commit | 39affe6c5629b78e418f33787ec7a9556b287832 (patch) | |
tree | c7951f6ec566334705e1a78ef0ba9bdba368ce8c | |
parent | 5b45f52e777fafb65fe9e4a53d202e38e3accdc9 (diff) | |
download | libmicrohttpd-39affe6c5629b78e418f33787ec7a9556b287832.tar.gz libmicrohttpd-39affe6c5629b78e418f33787ec7a9556b287832.zip |
adding MHD_run_from_select to API
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 42 | ||||
-rw-r--r-- | src/daemon/EXPORT.sym | 1 | ||||
-rw-r--r-- | src/daemon/daemon.c | 97 | ||||
-rw-r--r-- | src/include/microhttpd.h | 33 |
5 files changed, 146 insertions, 32 deletions
@@ -1,3 +1,8 @@ | |||
1 | Sun Mar 31 20:27:48 CEST 2013 | ||
2 | Adding new API call 'MHD_run_from_select' to allow programs | ||
3 | running in 'external select mode' to reduce the number of | ||
4 | 'select' calls by a factor of two. -CG | ||
5 | |||
1 | Sun Mar 31 20:03:48 CEST 2013 | 6 | Sun Mar 31 20:03:48 CEST 2013 |
2 | Performance improvements, updated documentation. | 7 | Performance improvements, updated documentation. |
3 | Make better use of available memory pool memory for | 8 | Make better use of available memory pool memory for |
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index b5284c3c..d82ebeb3 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -1095,11 +1095,53 @@ Shutdown an HTTP daemon. | |||
1095 | Run webserver operations (without blocking unless in client callbacks). | 1095 | Run webserver operations (without blocking unless in client callbacks). |
1096 | This method should be called by clients in combination with | 1096 | This method should be called by clients in combination with |
1097 | @code{MHD_get_fdset()} if the client-controlled @code{select}-method is used. | 1097 | @code{MHD_get_fdset()} if the client-controlled @code{select}-method is used. |
1098 | @cindex select | ||
1099 | @cindex poll | ||
1100 | |||
1101 | This function will work for external @code{poll} and @code{select} mode. | ||
1102 | However, if using external @code{select} mode, you may want to | ||
1103 | instead use @code{MHD_run_from_select}, as it is more efficient. | ||
1104 | |||
1105 | @table @var | ||
1106 | @item daemon | ||
1107 | daemon to process connections of | ||
1108 | @end table | ||
1098 | 1109 | ||
1099 | Return @code{MHD_YES} on success, @code{MHD_NO} if this daemon was not | 1110 | Return @code{MHD_YES} on success, @code{MHD_NO} if this daemon was not |
1100 | started with the right options for this call. | 1111 | started with the right options for this call. |
1101 | @end deftypefun | 1112 | @end deftypefun |
1102 | 1113 | ||
1114 | @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) | ||
1115 | Run webserver operations given sets of ready socket handles. | ||
1116 | @cindex select | ||
1117 | |||
1118 | This method should be called by clients in combination with | ||
1119 | @code{MHD_get_fdset} if the client-controlled (external) | ||
1120 | select method is used. | ||
1121 | |||
1122 | You can use this function instead of @code{MHD_run} if you called | ||
1123 | @code{select} on the result from @code{MHD_get_fdset}. File descriptors in | ||
1124 | the sets that are not controlled by MHD will be ignored. Calling | ||
1125 | this function instead of @code{MHD_run} is more efficient as MHD will | ||
1126 | not have to call @code{select} again to determine which operations are | ||
1127 | ready. | ||
1128 | |||
1129 | @table @var | ||
1130 | @item daemon | ||
1131 | daemon to process connections of | ||
1132 | @item read_fd_set | ||
1133 | set of descriptors that must be ready for reading without blocking | ||
1134 | @item write_fd_set | ||
1135 | set of descriptors that must be ready for writing without blocking | ||
1136 | @item except_fd_set | ||
1137 | ignored, can be NULL | ||
1138 | @end table | ||
1139 | |||
1140 | Return @code{MHD_YES} on success, @code{MHD_NO} on serious internal | ||
1141 | errors. | ||
1142 | |||
1143 | @end deftypefun | ||
1144 | |||
1103 | 1145 | ||
1104 | @deftypefun void MHD_add_connection (struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen) | 1146 | @deftypefun void MHD_add_connection (struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen) |
1105 | Add another client connection to the set of connections | 1147 | Add another client connection to the set of connections |
diff --git a/src/daemon/EXPORT.sym b/src/daemon/EXPORT.sym index 01418626..5c499b0b 100644 --- a/src/daemon/EXPORT.sym +++ b/src/daemon/EXPORT.sym | |||
@@ -4,6 +4,7 @@ MHD_stop_daemon | |||
4 | MHD_get_fdset | 4 | MHD_get_fdset |
5 | MHD_get_timeout | 5 | MHD_get_timeout |
6 | MHD_run | 6 | MHD_run |
7 | MHD_run_from_select | ||
7 | MHD_get_connection_values | 8 | MHD_get_connection_values |
8 | MHD_set_connection_value | 9 | MHD_set_connection_value |
9 | MHD_lookup_connection_value | 10 | MHD_lookup_connection_value |
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 72619c3d..bdd9f87b 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -1329,7 +1329,66 @@ MHD_get_timeout (struct MHD_Daemon *daemon, | |||
1329 | 1329 | ||
1330 | 1330 | ||
1331 | /** | 1331 | /** |
1332 | * Main select call. | 1332 | * Run webserver operations. This method should be called by clients |
1333 | * in combination with MHD_get_fdset if the client-controlled select | ||
1334 | * method is used. | ||
1335 | * | ||
1336 | * You can use this function instead of "MHD_run" if you called | ||
1337 | * 'select' on the result from "MHD_get_fdset". File descriptors in | ||
1338 | * the sets that are not controlled by MHD will be ignored. Calling | ||
1339 | * this function instead of "MHD_run" is more efficient as MHD will | ||
1340 | * not have to call 'select' again to determine which operations are | ||
1341 | * ready. | ||
1342 | * | ||
1343 | * @param daemon daemon to run select loop for | ||
1344 | * @param read_fd_set read set | ||
1345 | * @param write_fd_set write set | ||
1346 | * @param except_fd_set except set (not used, can be NULL) | ||
1347 | * @return MHD_NO on serious errors, MHD_YES on success | ||
1348 | */ | ||
1349 | int | ||
1350 | MHD_run_from_select (struct MHD_Daemon *daemon, | ||
1351 | const fd_set *read_fd_set, | ||
1352 | const fd_set *write_fd_set, | ||
1353 | const fd_set *except_fd_set) | ||
1354 | { | ||
1355 | int ds; | ||
1356 | struct MHD_Connection *pos; | ||
1357 | struct MHD_Connection *next; | ||
1358 | |||
1359 | /* select connection thread handling type */ | ||
1360 | if ( (-1 != (ds = daemon->socket_fd)) && | ||
1361 | (FD_ISSET (ds, read_fd_set)) ) | ||
1362 | MHD_accept_connection (daemon); | ||
1363 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | ||
1364 | { | ||
1365 | /* do not have a thread per connection, process all connections now */ | ||
1366 | next = daemon->connections_head; | ||
1367 | while (NULL != (pos = next)) | ||
1368 | { | ||
1369 | next = pos->next; | ||
1370 | ds = pos->socket_fd; | ||
1371 | if (ds != -1) | ||
1372 | { | ||
1373 | if ( (FD_ISSET (ds, read_fd_set)) | ||
1374 | #if HTTPS_SUPPORT | ||
1375 | || (MHD_YES == pos->tls_read_ready) | ||
1376 | #endif | ||
1377 | ) | ||
1378 | pos->read_handler (pos); | ||
1379 | if (FD_ISSET (ds, write_fd_set)) | ||
1380 | pos->write_handler (pos); | ||
1381 | pos->idle_handler (pos); | ||
1382 | } | ||
1383 | } | ||
1384 | } | ||
1385 | return MHD_YES; | ||
1386 | } | ||
1387 | |||
1388 | |||
1389 | /** | ||
1390 | * Main internal select call. Will compute select sets, call 'select' | ||
1391 | * and then MHD_run_from_select with the result. | ||
1333 | * | 1392 | * |
1334 | * @param daemon daemon to run select loop for | 1393 | * @param daemon daemon to run select loop for |
1335 | * @param may_block YES if blocking, NO if non-blocking | 1394 | * @param may_block YES if blocking, NO if non-blocking |
@@ -1339,8 +1398,6 @@ static int | |||
1339 | MHD_select (struct MHD_Daemon *daemon, | 1398 | MHD_select (struct MHD_Daemon *daemon, |
1340 | int may_block) | 1399 | int may_block) |
1341 | { | 1400 | { |
1342 | struct MHD_Connection *pos; | ||
1343 | struct MHD_Connection *next; | ||
1344 | int num_ready; | 1401 | int num_ready; |
1345 | fd_set rs; | 1402 | fd_set rs; |
1346 | fd_set ws; | 1403 | fd_set ws; |
@@ -1349,7 +1406,6 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1349 | struct timeval timeout; | 1406 | struct timeval timeout; |
1350 | struct timeval *tv; | 1407 | struct timeval *tv; |
1351 | MHD_UNSIGNED_LONG_LONG ltimeout; | 1408 | MHD_UNSIGNED_LONG_LONG ltimeout; |
1352 | int ds; | ||
1353 | 1409 | ||
1354 | timeout.tv_sec = 0; | 1410 | timeout.tv_sec = 0; |
1355 | timeout.tv_usec = 0; | 1411 | timeout.tv_usec = 0; |
@@ -1404,7 +1460,6 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1404 | tv = &timeout; | 1460 | tv = &timeout; |
1405 | } | 1461 | } |
1406 | num_ready = SELECT (max + 1, &rs, &ws, &es, tv); | 1462 | num_ready = SELECT (max + 1, &rs, &ws, &es, tv); |
1407 | |||
1408 | if (MHD_YES == daemon->shutdown) | 1463 | if (MHD_YES == daemon->shutdown) |
1409 | return MHD_NO; | 1464 | return MHD_NO; |
1410 | if (num_ready < 0) | 1465 | if (num_ready < 0) |
@@ -1416,33 +1471,7 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1416 | #endif | 1471 | #endif |
1417 | return MHD_NO; | 1472 | return MHD_NO; |
1418 | } | 1473 | } |
1419 | /* select connection thread handling type */ | 1474 | return MHD_run_from_select (daemon, &rs, &ws, &es); |
1420 | if ( (-1 != (ds = daemon->socket_fd)) && | ||
1421 | (FD_ISSET (ds, &rs)) ) | ||
1422 | MHD_accept_connection (daemon); | ||
1423 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | ||
1424 | { | ||
1425 | /* do not have a thread per connection, process all connections now */ | ||
1426 | next = daemon->connections_head; | ||
1427 | while (NULL != (pos = next)) | ||
1428 | { | ||
1429 | next = pos->next; | ||
1430 | ds = pos->socket_fd; | ||
1431 | if (ds != -1) | ||
1432 | { | ||
1433 | if ( (FD_ISSET (ds, &rs)) | ||
1434 | #if HTTPS_SUPPORT | ||
1435 | || (MHD_YES == pos->tls_read_ready) | ||
1436 | #endif | ||
1437 | ) | ||
1438 | pos->read_handler (pos); | ||
1439 | if (FD_ISSET (ds, &ws)) | ||
1440 | pos->write_handler (pos); | ||
1441 | pos->idle_handler (pos); | ||
1442 | } | ||
1443 | } | ||
1444 | } | ||
1445 | return MHD_YES; | ||
1446 | } | 1475 | } |
1447 | 1476 | ||
1448 | 1477 | ||
@@ -1647,6 +1676,10 @@ MHD_poll (struct MHD_Daemon *daemon, | |||
1647 | * by clients in combination with MHD_get_fdset | 1676 | * by clients in combination with MHD_get_fdset |
1648 | * if the client-controlled select method is used. | 1677 | * if the client-controlled select method is used. |
1649 | * | 1678 | * |
1679 | * This function will work for external 'poll' and 'select' mode. | ||
1680 | * However, if using external 'select' mode, you may want to | ||
1681 | * instead use 'MHD_run_from_select', as it is more efficient. | ||
1682 | * | ||
1650 | * @return MHD_YES on success, MHD_NO if this | 1683 | * @return MHD_YES on success, MHD_NO if this |
1651 | * daemon was not started with the right | 1684 | * daemon was not started with the right |
1652 | * options for this call. | 1685 | * options for this call. |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 3d406c2e..4da26191 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -1182,6 +1182,14 @@ int MHD_get_timeout (struct MHD_Daemon *daemon, | |||
1182 | * by clients in combination with MHD_get_fdset | 1182 | * by clients in combination with MHD_get_fdset |
1183 | * if the client-controlled select method is used. | 1183 | * if the client-controlled select method is used. |
1184 | * | 1184 | * |
1185 | * This function is a convenience method, which is useful if the | ||
1186 | * fd_sets from "MHD_get_fdset" were not directly passed to 'select'; | ||
1187 | * with this function, MHD will internally do the appropriate 'select' | ||
1188 | * call itself again. While it is always safe to call 'MHD_run' (in | ||
1189 | * external select mode), you should call 'MHD_run_from_select' if | ||
1190 | * performance is important (as it saves an expensive call to | ||
1191 | * 'select'). | ||
1192 | * | ||
1185 | * @param daemon daemon to run | 1193 | * @param daemon daemon to run |
1186 | * @return MHD_YES on success, MHD_NO if this | 1194 | * @return MHD_YES on success, MHD_NO if this |
1187 | * daemon was not started with the right | 1195 | * daemon was not started with the right |
@@ -1191,6 +1199,31 @@ int | |||
1191 | MHD_run (struct MHD_Daemon *daemon); | 1199 | MHD_run (struct MHD_Daemon *daemon); |
1192 | 1200 | ||
1193 | 1201 | ||
1202 | /** | ||
1203 | * Run webserver operations. This method should be called by clients | ||
1204 | * in combination with MHD_get_fdset if the client-controlled select | ||
1205 | * method is used. | ||
1206 | * | ||
1207 | * You can use this function instead of "MHD_run" if you called | ||
1208 | * 'select' on the result from "MHD_get_fdset". File descriptors in | ||
1209 | * the sets that are not controlled by MHD will be ignored. Calling | ||
1210 | * this function instead of "MHD_run" is more efficient as MHD will | ||
1211 | * not have to call 'select' again to determine which operations are | ||
1212 | * ready. | ||
1213 | * | ||
1214 | * @param daemon daemon to run select loop for | ||
1215 | * @param read_fd_set read set | ||
1216 | * @param write_fd_set write set | ||
1217 | * @param except_fd_set except set (not used, can be NULL) | ||
1218 | * @return MHD_NO on serious errors, MHD_YES on success | ||
1219 | */ | ||
1220 | int | ||
1221 | MHD_run_from_select (struct MHD_Daemon *daemon, | ||
1222 | const fd_set *read_fd_set, | ||
1223 | const fd_set *write_fd_set, | ||
1224 | const fd_set *except_fd_set); | ||
1225 | |||
1226 | |||
1194 | /* **************** Connection handling functions ***************** */ | 1227 | /* **************** Connection handling functions ***************** */ |
1195 | 1228 | ||
1196 | /** | 1229 | /** |