diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-08-04 17:17:42 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-08-04 21:20:00 -0700 |
| commit | dc334d7193a2a0bc0194221b853a37e1be7f5b9a (patch) | |
| tree | 1eebf2773745a3a25e8a071fbe4f51cd5490d4e4 /src/core/aio.h | |
| parent | 6887900ae033add30ee0151b72abe927c5239588 (diff) | |
| download | nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.tar.gz nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.tar.bz2 nng-dc334d7193a2a0bc0194221b853a37e1be7f5b9a.zip | |
Refactor AIO logic to close numerous races and reduce complexity.
This passes valgrind 100% clean for both helgrind and deep leak
checks. This represents a complete rethink of how the AIOs work,
and much simpler synchronization; the provider API is a bit simpler
to boot, as a number of failure modes have been simply eliminated.
While here a few other minor bugs were squashed.
Diffstat (limited to 'src/core/aio.h')
| -rw-r--r-- | src/core/aio.h | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/src/core/aio.h b/src/core/aio.h index 31a54f12..0f41c01f 100644 --- a/src/core/aio.h +++ b/src/core/aio.h @@ -18,6 +18,8 @@ typedef struct nni_aio_ops nni_aio_ops; +typedef void (*nni_aio_cancelfn)(nni_aio *, int); + // An nni_aio is an async I/O handle. struct nni_aio { int a_result; // Result code (nng_errno) @@ -25,10 +27,14 @@ struct nni_aio { nni_time a_expire; // These fields are private to the aio framework. - nni_mtx a_lk; nni_cv a_cv; - unsigned a_flags; - int a_refcnt; // prevent use-after-free + unsigned a_init : 1; // initialized flag + unsigned a_fini : 1; // shutting down (no new operations) + unsigned a_done : 1; // operation has completed + unsigned a_pend : 1; // completion routine pending + unsigned a_active : 1; // aio was started + unsigned a_expiring : 1; // expiration callback in progress + unsigned a_pad : 27; // ensure 32-bit alignment nni_task a_task; // Read/write operations. @@ -47,9 +53,9 @@ struct nni_aio { int a_naddrs; // Provider-use fields. - void (*a_prov_cancel)(nni_aio *); - void * a_prov_data; - nni_list_node a_prov_node; + nni_aio_cancelfn a_prov_cancel; + void * a_prov_data; + nni_list_node a_prov_node; // Expire node. nni_list_node a_expire_node; @@ -106,21 +112,17 @@ extern void nni_aio_list_remove(nni_aio *); extern int nni_aio_list_active(nni_aio *); // nni_aio_finish is called by the provider when an operation is complete. -// The provider gives the result code (0 for success, an NNG errno otherwise), -// and the amount of data transferred (if any). If the return code is -// non-zero, it indicates that the operation failed (usually because the aio -// was already canceled.) This is important for providers that need to -// prevent resources (new pipes for example) from accidentally leaking -// during close operations. -extern int nni_aio_finish(nni_aio *, int, size_t); -extern int nni_aio_finish_pipe(nni_aio *, int, void *); +extern void nni_aio_finish(nni_aio *, int, size_t); +extern void nni_aio_finish_error(nni_aio *, int); +extern void nni_aio_finish_pipe(nni_aio *, void *); +extern void nni_aio_finish_msg(nni_aio *, nni_msg *); // nni_aio_cancel is used to cancel an operation. Any pending I/O or // timeouts are canceled if possible, and the callback will be returned // with the indicated result (NNG_ECLOSED or NNG_ECANCELED is recommended.) extern void nni_aio_cancel(nni_aio *, int rv); -extern int nni_aio_start(nni_aio *, void (*)(nni_aio *), void *); +extern int nni_aio_start(nni_aio *, nni_aio_cancelfn, void *); // nni_aio_stop is used to abort all further operations on the AIO. // When this is executed, no further operations or callbacks will be |
