aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asyn-ares.c2
-rw-r--r--lib/asyn-thread.c2
-rw-r--r--lib/connect.c2
-rw-r--r--lib/multi.c46
-rw-r--r--lib/multiif.h1
-rw-r--r--lib/speedcheck.c6
6 files changed, 50 insertions, 9 deletions
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index cb99a1f46..01a9c9b50 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -235,7 +235,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire(conn->data, milli);
+ Curl_expire_latest(conn->data, milli);
return max;
}
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 6cdc9adff..e4ad32bb7 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -541,7 +541,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
- Curl_expire(conn->data, td->poll_interval);
+ Curl_expire_latest(conn->data, td->poll_interval);
}
return CURLE_OK;
diff --git a/lib/connect.c b/lib/connect.c
index 6a79e64de..fb315fc8d 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -1054,7 +1054,7 @@ singleipconnect(struct connectdata *conn,
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
- Curl_expire(data, conn->timeoutms_per_addr);
+ Curl_expire_latest(data, conn->timeoutms_per_addr);
/* Connect TCP sockets, bind UDP */
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
diff --git a/lib/multi.c b/lib/multi.c
index 20fc372fa..557be06df 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1491,7 +1491,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->set.buffer_size : BUFSIZE);
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
data->progress.ulspeed, buffersize);
- Curl_expire(data, timeout_ms);
+ Curl_expire_latest(data, timeout_ms);
break;
}
@@ -1507,7 +1507,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->set.buffer_size : BUFSIZE);
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
data->progress.dlspeed, buffersize);
- Curl_expire(data, timeout_ms);
+ Curl_expire_latest(data, timeout_ms);
break;
}
@@ -1569,7 +1569,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* expire the new receiving pipeline head */
if(data->easy_conn->recv_pipe->head)
- Curl_expire(data->easy_conn->recv_pipe->head->ptr, 1);
+ Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
/* Check if we can move pending requests to send pipe */
Curl_multi_process_pending_handles(multi);
@@ -2682,6 +2682,46 @@ void Curl_expire(struct SessionHandle *data, long milli)
#endif
}
+/*
+ * Curl_expire_latest()
+ *
+ * This is like Curl_expire() but will only add a timeout node to the list of
+ * timers if there is no timeout that will expire before the given time.
+ *
+ * Use this function if the code logic risks calling this function many times
+ * or if there's no particular conditional wait in the code for this specific
+ * time-out period to expire.
+ *
+ */
+void Curl_expire_latest(struct SessionHandle *data, long milli)
+{
+ struct timeval *exp = &data->state.expiretime;
+
+ struct timeval set;
+
+ set = Curl_tvnow();
+ set.tv_sec += milli/1000;
+ set.tv_usec += (milli%1000)*1000;
+
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
+ }
+
+ if(exp->tv_sec || exp->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ long diff = curlx_tvdiff(set, *exp);
+ if(diff > 0)
+ /* the new expire time was later than the top time, so just skip this */
+ return;
+ }
+
+ /* Just add the timeout like normal */
+ Curl_expire(data, milli);
+}
+
CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t s, void *hashp)
{
diff --git a/lib/multiif.h b/lib/multiif.h
index 1cbd31009..c77b3ca3b 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -26,6 +26,7 @@
* Prototypes for library-wide functions provided by multi.c
*/
void Curl_expire(struct SessionHandle *data, long milli);
+void Curl_expire_latest(struct SessionHandle *data, long milli);
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index ea17a5975..ac7447c41 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,7 +57,7 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
}
else {
/* wait complete low_speed_time */
- Curl_expire(data, nextcheck);
+ Curl_expire_latest(data, nextcheck);
}
}
else {
@@ -68,7 +68,7 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
/* if there is a low speed limit enabled, we set the expire timer to
make this connection's speed get checked again no later than when
this time is up */
- Curl_expire(data, data->set.low_speed_time*1000);
+ Curl_expire_latest(data, data->set.low_speed_time*1000);
}
return CURLE_OK;
}