From 05d06eff66ad0fffa1e26cde1278144196ac37f3 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Sat, 4 Oct 2025 20:59:35 -0400 Subject: adds nng_dialer_start_aio (#2163) * adds nng_dialer_start_aio This change adds `nng_dialer_start_aio` (if you have a better name, I'm happy to change it), whose docs read: > `nng_dialer_start_aio` starts the endpoint dialing asynchronously. > This is only possible if the dialer is not already dialing. Unlike > `nng_dialer_start`, this accepts an AIO such that the caller can learn > when the dialing eventually succeeds or fails. The supplied AIO must > have been initialized, and is only triggered with the result of the > first dial attempt. This new function makes it possible for applications to perform a non-blocking dial, but still later be notified of the result of that dial. Arguably, this obviates the need for `NNG_FLAG_NONBLOCK` in `dialer_start` altogether, but no need to break backwards compatibility. There is technically a functional change here, which is that the "Starting dialer for socket" message now gets printed _before_ the dial is complete in the blocking case, rather than after. It's possible to change this if we're willing to make the code slightly more complicated, but given it says "Starting", not "Started", this change felt fine. --- src/core/dialer.c | 37 ++++++++++++++++++++++++++++--------- src/core/dialer.h | 1 + src/nng.c | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/dialer.c b/src/core/dialer.c index bef110d7..9b868224 100644 --- a/src/core/dialer.c +++ b/src/core/dialer.c @@ -458,22 +458,16 @@ nni_dialer_start(nni_dialer *d, unsigned flags) nni_aio aio; nni_aio *aiop = NULL; - if (nni_atomic_flag_test_and_set(&d->d_started)) { - return (NNG_ESTATE); - } - if ((flags & NNG_FLAG_NONBLOCK) != 0) { aiop = NULL; } else { nni_aio_init(&aio, NULL, NULL); aiop = &aio; - nni_aio_start(aiop, NULL, NULL); } - nni_mtx_lock(&d->d_mtx); - d->d_user_aio = aiop; - dialer_connect_start(d); - nni_mtx_unlock(&d->d_mtx); + if ((rv = nni_dialer_start_aio(d, flags, aiop)) != 0) { + return (rv); + } if (aiop != NULL) { nni_aio_wait(aiop); @@ -481,6 +475,31 @@ nni_dialer_start(nni_dialer *d, unsigned flags) nni_aio_fini(aiop); } + return (rv); +} + +int +nni_dialer_start_aio(nni_dialer *d, unsigned flags, nni_aio *aiop) +{ + int rv = 0; + + if (nni_atomic_flag_test_and_set(&d->d_started)) { + return (NNG_ESTATE); + } + + if (aiop != NULL) { + nni_aio_start(aiop, NULL, NULL); + } + + // Note that flags is currently unused, since the only flag is + // NONBLOCK, which is handled in callers. + NNI_ARG_UNUSED(flags); + + nni_mtx_lock(&d->d_mtx); + d->d_user_aio = aiop; + dialer_connect_start(d); + nni_mtx_unlock(&d->d_mtx); + nng_log_info("NNG-DIAL", "Starting dialer for socket<%u>", nni_sock_id(d->d_sock)); diff --git a/src/core/dialer.h b/src/core/dialer.h index bd987866..26cd5c0d 100644 --- a/src/core/dialer.h +++ b/src/core/dialer.h @@ -23,6 +23,7 @@ extern int nni_dialer_create(nni_dialer **, nni_sock *, const char *); extern int nni_dialer_create_url(nni_dialer **, nni_sock *, const nng_url *); extern void nni_dialer_close(nni_dialer *); extern int nni_dialer_start(nni_dialer *, unsigned); +extern int nni_dialer_start_aio(nni_dialer *, unsigned, nni_aio *); extern nni_sock *nni_dialer_sock(nni_dialer *); extern int nni_dialer_setopt( diff --git a/src/nng.c b/src/nng.c index a425d599..9b155599 100644 --- a/src/nng.c +++ b/src/nng.c @@ -666,6 +666,30 @@ nng_dialer_start(nng_dialer did, int flags) return (rv); } +void +nng_dialer_start_aio(nng_dialer did, int flags, nng_aio *aio) +{ + nni_dialer *d; + int rv; + + if (aio != NULL) { + nni_aio_reset(aio); + } + if ((flags & NNG_FLAG_NONBLOCK) == 0) { + nni_aio_finish_error(aio, NNG_EINVAL); + return; + } + if ((rv = nni_dialer_find(&d, did.id)) != 0) { + nni_aio_finish_error(aio, rv); + return; + } + if ((rv = nni_dialer_start_aio(d, flags, aio)) != 0) { + nni_aio_finish_error(aio, rv); + // fall-through + } + nni_dialer_rele(d); +} + int nng_dialer_id(nng_dialer d) { -- cgit v1.2.3-70-g09d2