From 722bf4621703ef238fa81018f8c3e68bcef91354 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Mon, 18 Apr 2022 10:25:03 -0400 Subject: [PATCH] fixes #1574 Non-blocking version of nng_aio_wait / nng_aio_result This introduces a new API, nng_aio_busy(), that can be used to query the status of the aio without blocking. Some minor documentation fixes are included. --- docs/man/libnng.3.adoc | 1 + docs/man/nng_aio_alloc.3.adoc | 4 +-- docs/man/nng_aio_busy.3.adoc | 56 +++++++++++++++++++++++++++++++++++ docs/man/nng_aio_wait.3.adoc | 5 ++-- include/nng/nng.h | 6 ++++ src/core/aio.c | 8 ++++- src/core/aio.h | 6 +++- src/core/aio_test.c | 15 +++++++++- src/core/taskq.c | 20 +++++++++---- src/core/taskq.h | 9 +++++- src/nng.c | 8 ++++- 11 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 docs/man/nng_aio_busy.3.adoc diff --git a/docs/man/libnng.3.adoc b/docs/man/libnng.3.adoc index 7475cdca3..eaeae24db 100644 --- a/docs/man/libnng.3.adoc +++ b/docs/man/libnng.3.adoc @@ -164,6 +164,7 @@ The following functions are used in the asynchronous model: |xref:nng_aio_abort.3.adoc[nng_aio_abort()]|abort asynchronous I/O operation |xref:nng_aio_alloc.3.adoc[nng_aio_alloc()]|allocate asynchronous I/O handle |xref:nng_aio_begin.3.adoc[nng_aio_begin()]|begin asynchronous I/O operation +|xref:nng_aio_busy.3.adoc[nng_aio_busy()]|test if asynchronous I/O is busy |xref:nng_aio_cancel.3.adoc[nng_aio_cancel()]|cancel asynchronous I/O operation |xref:nng_aio_count.3.adoc[nng_aio_count()]|return number of bytes transferred |xref:nng_aio_defer.3.adoc[nng_aio_defer()]|defer asynchronous I/O operation diff --git a/docs/man/nng_aio_alloc.3.adoc b/docs/man/nng_aio_alloc.3.adoc index 3a4a95e17..6a424e3bc 100644 --- a/docs/man/nng_aio_alloc.3.adoc +++ b/docs/man/nng_aio_alloc.3.adoc @@ -1,6 +1,6 @@ = nng_aio_alloc(3) // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This document is supplied under the terms of the MIT License, a @@ -37,7 +37,7 @@ This also means you should avoid operations such as allocating new objects, which also means opening or closing sockets, dialers, and so forth. TIP: If more complex or blocking work needs to be performed by _callb_, a separate -thread can be used, along with a xref:nng_cv_alloc.3.adoc[condition variable] +thread can be used, along with a xref:nng_cv_alloc.3supp.adoc[condition variable] which can be signaled by the callback. Asynchronous I/O operations all take an xref:nng_aio.5.adoc[`nng_aio`] diff --git a/docs/man/nng_aio_busy.3.adoc b/docs/man/nng_aio_busy.3.adoc new file mode 100644 index 000000000..4aaf09b53 --- /dev/null +++ b/docs/man/nng_aio_busy.3.adoc @@ -0,0 +1,56 @@ += nng_aio_busy(3) +// +// Copyright 2022 Staysail Systems, Inc. +// +// This document is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +== NAME + +nng_aio_busy - test if asynchronous I/O is busy + +== SYNOPSIS + +[source, c] +---- +#include + +bool nng_aio_busy(nng_aio *aio); +---- + +== DESCRIPTION + +The `nng_aio_busy()` function returns true if the +_aio_ is currently busy performing an asynchronous I/O +operation or is executing a completion callback. + +If no operation has been started, or the operation has +been completed or canceled, and any callback has been +executed, then it returns false. + +This is the same test used internally by +xref:nng_aio_wait.3.adoc[`nng_aio_wait()`] + +NOTE: Care should be taken to ensure that the _aio_ object is not +freed when using this function. The caller is responsible for +coordinating any use of this with any reuse of the _aio_. + +== RETURN VALUES + +True if the _aio_ is busy, false otherwise. + +== ERRORS + +None. + +== SEE ALSO + +[.text-left] +xref:nng_aio_abort.3.adoc[nng_aio_abort(3)], +xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)], +xref:nng_aio_wait.3.adoc[nng_aio_wait(3)], +xref:nng_aio.5.adoc[nng_aio(5)], +xref:nng.7.adoc[nng(7)] diff --git a/docs/man/nng_aio_wait.3.adoc b/docs/man/nng_aio_wait.3.adoc index 5b65c79e0..18b735db9 100644 --- a/docs/man/nng_aio_wait.3.adoc +++ b/docs/man/nng_aio_wait.3.adoc @@ -1,6 +1,6 @@ = nng_aio_wait(3) // -// Copyright 2018 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This document is supplied under the terms of the MIT License, a @@ -29,7 +29,7 @@ to complete. If the operation has not been started, or has already completed, then it returns immediately. -If the a callback was set with _aio_ when it was allocated, then this +If a callback was set with _aio_ when it was allocated, then this function will not be called until the callback has completed. == RETURN VALUES @@ -45,5 +45,6 @@ None. [.text-left] xref:nng_aio_abort.3.adoc[nng_aio_abort(3)], xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)], +xref:nng_aio_busy.3.adoc[nng_aio_busy(3)], xref:nng_aio.5.adoc[nng_aio(5)], xref:nng.7.adoc[nng(7)] diff --git a/include/nng/nng.h b/include/nng/nng.h index 9aa9ed9a5..811cb456b 100644 --- a/include/nng/nng.h +++ b/include/nng/nng.h @@ -544,6 +544,12 @@ NNG_DECL void nng_aio_abort(nng_aio *, int); // callback or deadlock may occur. NNG_DECL void nng_aio_wait(nng_aio *); +// nng_aio_busy returns true if the aio is still busy processing the +// operation, or executing associated completion functions. Note that +// if the completion function schedules a new operation using the aio, +// then this function will continue to return true. +NNG_DECL bool nng_aio_busy(nng_aio *); + // nng_aio_set_msg sets the message structure to use for asynchronous // message send operations. NNG_DECL void nng_aio_set_msg(nng_aio *, nng_msg *); diff --git a/src/core/aio.c b/src/core/aio.c index 65d8b984c..771cbc952 100644 --- a/src/core/aio.c +++ b/src/core/aio.c @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -314,6 +314,12 @@ nni_aio_wait(nni_aio *aio) nni_task_wait(&aio->a_task); } +bool +nni_aio_busy(nni_aio *aio) +{ + return (nni_task_busy(&aio->a_task)); +} + int nni_aio_begin(nni_aio *aio) { diff --git a/src/core/aio.h b/src/core/aio.h index d1d4cf798..6315e90c9 100644 --- a/src/core/aio.h +++ b/src/core/aio.h @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -93,6 +93,10 @@ extern int nni_aio_result(nni_aio *); // completed. extern size_t nni_aio_count(nni_aio *); +// nni_aio_busy returns true if the aio is still busy processing work. +// This is a non-blocking form of the check used by nni_aio_wait(). +extern bool nni_aio_busy(nni_aio *); + // nni_aio_wait blocks the caller until the operation is complete. // The operation must have already been started. This routine will // block until the AIO, as well as any callback, has completed execution. diff --git a/src/core/aio_test.c b/src/core/aio_test.c index a94978bc9..bbc997b5c 100644 --- a/src/core/aio_test.c +++ b/src/core/aio_test.c @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -364,6 +364,18 @@ test_sleep_cancel(void) nng_mtx_free(sl.mx); } +void + test_aio_busy(void) +{ + nng_aio *aio; + NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nng_sleep_aio(100, aio); + NUTS_ASSERT(nng_aio_busy(aio)); + nng_aio_wait(aio); + NUTS_ASSERT(!nng_aio_busy(aio)); + nng_aio_free(aio); +} + NUTS_TESTS = { { "sleep", test_sleep }, { "sleep timeout", test_sleep_timeout }, @@ -377,5 +389,6 @@ NUTS_TESTS = { { "aio reap", test_aio_reap }, { "sleep loop", test_sleep_loop }, { "sleep cancel", test_sleep_cancel }, + { "aio busy", test_aio_busy }, { NULL, NULL }, }; \ No newline at end of file diff --git a/src/core/taskq.c b/src/core/taskq.c index e06bc264d..d914093bf 100644 --- a/src/core/taskq.c +++ b/src/core/taskq.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -31,12 +31,12 @@ static void nni_taskq_thread(void *self) { nni_taskq_thr *thr = self; - nni_taskq * tq = thr->tqt_tq; - nni_task * task; + nni_taskq *tq = thr->tqt_tq; + nni_task *task; - nni_thr_set_name(NULL, "nng:task"); + nni_thr_set_name(NULL, "nng:task"); - nni_mtx_lock(&tq->tq_mtx); + nni_mtx_lock(&tq->tq_mtx); for (;;) { if ((task = nni_list_first(&tq->tq_tasks)) != NULL) { @@ -207,6 +207,16 @@ nni_task_wait(nni_task *task) nni_mtx_unlock(&task->task_mtx); } +bool +nni_task_busy(nni_task *task) +{ + bool busy; + nni_mtx_lock(&task->task_mtx); + busy = task->task_busy; + nni_mtx_unlock(&task->task_mtx); + return (busy); +} + void nni_task_init(nni_task *task, nni_taskq *tq, nni_cb cb, void *arg) { diff --git a/src/core/taskq.h b/src/core/taskq.h index 9cabfd9b8..2ff449cfd 100644 --- a/src/core/taskq.h +++ b/src/core/taskq.h @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -43,6 +43,13 @@ extern void nni_task_prep(nni_task *); // returns an error. extern void nni_task_abort(nni_task *); +// nni_task_busy checks to see if a task is still busy. +// This is uses the same check that nni_task_wait uses. +extern bool nni_task_busy(nni_task *); + +// nni_task_wait waits for the task to complete. If additional +// work is scheduled on the task then it will not return until that +// work (or any other work subsequently scheduled) is complete. extern void nni_task_wait(nni_task *); extern void nni_task_init(nni_task *, nni_taskq *, nni_cb, void *); diff --git a/src/nng.c b/src/nng.c index c48ccd0be..792595682 100644 --- a/src/nng.c +++ b/src/nng.c @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2022 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -1883,6 +1883,12 @@ nng_aio_wait(nng_aio *aio) nni_aio_wait(aio); } +bool +nng_aio_busy(nng_aio *aio) +{ + return (nni_aio_busy(aio)); +} + void nng_aio_abort(nng_aio *aio, int err_code) {