mirror of
https://github.com/curl/curl.git
synced 2026-08-15 03:03:37 +03:00
curl_multi_poll: a sister to curl_multi_wait() that waits more
Repeatedly we see problems where using curl_multi_wait() is difficult or just awkward because if it has no file descriptor to wait for internally, it returns immediately and leaves it to the caller to wait for a small amount of time in order to avoid occasional busy-looping. This is often missed or misunderstood, leading to underperforming applications. This change introduces curl_multi_poll() as a replacement drop-in function that accepts the exact same set of arguments. This function works identically to curl_multi_wait() - EXCEPT - for the case when there's nothing to wait for internally, as then this function will by itself wait for a "suitable" short time before it returns. This effectiely avoids all risks of busy-looping and should also make it less likely that apps "over-wait". This also changes the curl tool to use this funtion internally when doing parallel transfers and changes curl_easy_perform() to use it internally. Closes #4163
This commit is contained in:
parent
cee7639b79
commit
02346abc32
9 changed files with 160 additions and 79 deletions
|
|
@ -1904,23 +1904,6 @@ static CURLcode create_transfers(struct GlobalConfig *global,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* portable millisecond sleep */
|
||||
static void wait_ms(int ms)
|
||||
{
|
||||
#if defined(MSDOS)
|
||||
delay(ms);
|
||||
#elif defined(WIN32)
|
||||
Sleep(ms);
|
||||
#elif defined(HAVE_USLEEP)
|
||||
usleep(1000 * ms);
|
||||
#else
|
||||
struct timeval pending_tv;
|
||||
pending_tv.tv_sec = ms / 1000;
|
||||
pending_tv.tv_usec = (ms % 1000) * 1000;
|
||||
(void)select(0, NULL, NULL, NULL, &pending_tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
static long all_added; /* number of easy handles currently added */
|
||||
|
||||
static int add_parallel_transfers(struct GlobalConfig *global,
|
||||
|
|
@ -1971,30 +1954,9 @@ static CURLcode parallel_transfers(struct GlobalConfig *global,
|
|||
return result;
|
||||
|
||||
while(!done && !mcode && still_running) {
|
||||
int numfds;
|
||||
struct timeval before = tvnow();
|
||||
long delta;
|
||||
|
||||
mcode = curl_multi_wait(multi, NULL, 0, 1000, &numfds);
|
||||
delta = tvdiff(tvnow(), before);
|
||||
|
||||
if(!mcode) {
|
||||
if(!numfds && (delta < 30)) {
|
||||
long sleep_ms;
|
||||
|
||||
/* If it returns without any file descriptor instantly, we need to
|
||||
avoid busy-looping during periods where it has nothing particular
|
||||
to wait for */
|
||||
curl_multi_timeout(multi, &sleep_ms);
|
||||
if(sleep_ms) {
|
||||
if(sleep_ms > 1000)
|
||||
sleep_ms = 1000;
|
||||
wait_ms((int)sleep_ms);
|
||||
}
|
||||
}
|
||||
|
||||
mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL);
|
||||
if(!mcode)
|
||||
mcode = curl_multi_perform(multi, &still_running);
|
||||
}
|
||||
|
||||
progress_meter(global, &start, FALSE);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue