aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2022-04-18 10:25:03 -0400
committerGarrett D'Amore <garrett@damore.org>2022-04-18 17:41:21 -0400
commit722bf4621703ef238fa81018f8c3e68bcef91354 (patch)
tree1389cd6082ecae9ab0db1239f48861ebefea3c4c
parentd9897897fcf9d1276190b5d20955c72fd632acac (diff)
downloadnng-722bf4621703ef238fa81018f8c3e68bcef91354.tar.gz
nng-722bf4621703ef238fa81018f8c3e68bcef91354.tar.bz2
nng-722bf4621703ef238fa81018f8c3e68bcef91354.zip
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.
-rw-r--r--docs/man/libnng.3.adoc1
-rw-r--r--docs/man/nng_aio_alloc.3.adoc4
-rw-r--r--docs/man/nng_aio_busy.3.adoc56
-rw-r--r--docs/man/nng_aio_wait.3.adoc5
-rw-r--r--include/nng/nng.h6
-rw-r--r--src/core/aio.c8
-rw-r--r--src/core/aio.h6
-rw-r--r--src/core/aio_test.c15
-rw-r--r--src/core/taskq.c20
-rw-r--r--src/core/taskq.h9
-rw-r--r--src/nng.c8
11 files changed, 124 insertions, 14 deletions
diff --git a/docs/man/libnng.3.adoc b/docs/man/libnng.3.adoc
index 7475cdca..eaeae24d 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 3a4a95e1..6a424e3b 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. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 00000000..4aaf09b5
--- /dev/null
+++ b/docs/man/nng_aio_busy.3.adoc
@@ -0,0 +1,56 @@
+= nng_aio_busy(3)
+//
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
+//
+// 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 <nng/nng.h>
+
+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 5b65c79e..18b735db 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. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 9aa9ed9a..811cb456 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 65d8b984..771cbc95 100644
--- a/src/core/aio.c
+++ b/src/core/aio.c
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 d1d4cf79..6315e90c 100644
--- a/src/core/aio.h
+++ b/src/core/aio.h
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 a94978bc..bbc997b5 100644
--- a/src/core/aio_test.c
+++ b/src/core/aio_test.c
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 e06bc264..d914093b 100644
--- a/src/core/taskq.c
+++ b/src/core/taskq.c
@@ -1,5 +1,5 @@
//
-// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 9cabfd9b..2ff449cf 100644
--- a/src/core/taskq.h
+++ b/src/core/taskq.h
@@ -1,5 +1,5 @@
//
-// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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 c48ccd0b..79259568 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// 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)
{