summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-03-12 17:37:33 -0700
committerGarrett D'Amore <garrett@damore.org>2018-03-12 17:37:33 -0700
commit55e98ae58c5856c1808e3fccb2548a76c9b8907c (patch)
tree8dcb25ea029f87074276ad01d2bda21d1746ca5b /src
parent2f1e799d1225b18e960d426d35b6a83fa80db86f (diff)
downloadnng-55e98ae58c5856c1808e3fccb2548a76c9b8907c.tar.gz
nng-55e98ae58c5856c1808e3fccb2548a76c9b8907c.tar.bz2
nng-55e98ae58c5856c1808e3fccb2548a76c9b8907c.zip
nng_sleep_aio should honor aio timeout.
The first problem was that using nng_sleep_aio was found to reset the timeout, and this caused subsequent operations to start failing with timeouts when reusing the AIO for other operations. The second thing is that we think it would be nicer if the presence of real aio timeouts were still honored, so that if the timeout is shorter than the sleep time, then we get back an NNG_ETIMEDOUT like every other operation, and we get back a 0 if the logical sleep operation completes normally.
Diffstat (limited to 'src')
-rw-r--r--src/core/aio.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/src/core/aio.c b/src/core/aio.c
index e0206830..1aaffe12 100644
--- a/src/core/aio.c
+++ b/src/core/aio.c
@@ -321,19 +321,24 @@ nni_aio_start(nni_aio *aio, nni_aio_cancelfn cancelfn, void *data)
}
// Convert the relative timeout to an absolute timeout.
- switch (aio->a_timeout) {
- case NNG_DURATION_ZERO:
- aio->a_expire = NNI_TIME_ZERO;
- nni_aio_expire_add(aio);
- break;
- case NNG_DURATION_INFINITE:
- case NNG_DURATION_DEFAULT:
- aio->a_expire = NNI_TIME_NEVER;
- break;
- default:
- aio->a_expire = nni_clock() + aio->a_timeout;
+ if (aio->a_sleep) {
+ // expire node already set.
nni_aio_expire_add(aio);
- break;
+ } else {
+ switch (aio->a_timeout) {
+ case NNG_DURATION_ZERO:
+ aio->a_expire = NNI_TIME_ZERO;
+ nni_aio_expire_add(aio);
+ break;
+ case NNG_DURATION_INFINITE:
+ case NNG_DURATION_DEFAULT:
+ aio->a_expire = NNI_TIME_NEVER;
+ break;
+ default:
+ aio->a_expire = nni_clock() + aio->a_timeout;
+ nni_aio_expire_add(aio);
+ break;
+ }
}
nni_mtx_unlock(&nni_aio_lk);
return (0);
@@ -517,10 +522,11 @@ nni_aio_expire_loop(void *arg)
// already being canceled or finished.
if (cancelfn != NULL) {
nni_mtx_unlock(&nni_aio_lk);
- cancelfn(aio, aio->a_sleep ? 0 : NNG_ETIMEDOUT);
+ cancelfn(aio, rv);
nni_mtx_lock(&nni_aio_lk);
} else {
- aio->a_pend = 1;
+ aio->a_pend = 1;
+ aio->a_result = rv;
}
NNI_ASSERT(aio->a_pend); // nni_aio_finish was run
@@ -621,11 +627,23 @@ nni_aio_iov_advance(nni_aio *aio, size_t n)
void
nni_sleep_aio(nng_duration ms, nng_aio *aio)
{
- nni_aio_set_timeout(aio, ms);
- aio->a_sleep = 1;
- if (nni_aio_start(aio, NULL, NULL)) {
- return;
+ switch (aio->a_timeout) {
+ case NNG_DURATION_DEFAULT:
+ case NNG_DURATION_INFINITE:
+ // No premature timeout, honor our expected values.
+ break;
+ default:
+ // If the timeout on the aio is shorter than our sleep time,
+ // then let it still wake up early, but with NNG_ETIMEDOUT.
+ if (ms > aio->a_timeout) {
+ aio->a_sleep = 0;
+ (void) nni_aio_start(aio, NULL, NULL);
+ return;
+ }
}
+ aio->a_sleep = 1;
+ aio->a_expire = nni_clock() + ms;
+ (void) nni_aio_start(aio, NULL, NULL);
}
void