aboutsummaryrefslogtreecommitdiff
path: root/src/core/aio.h
blob: a290281f63b073610c45887684c15a55d92507a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
//
// This software 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.
//

#ifndef CORE_AIO_H
#define CORE_AIO_H

#include "core/defs.h"
#include "core/list.h"
#include "core/taskq.h"
#include "core/thread.h"

typedef struct nni_aio_ops   nni_aio_ops;

// An nni_aio is an async I/O handle.
struct nni_aio {
	int		a_result;       // Result code (nng_errno)
	size_t		a_count;        // Bytes transferred (I/O only)
	nni_cb		a_cb;           // User specified callback.
	void *		a_cbarg;        // Callback argument.
	nni_time	a_expire;

	// These fields are private to the aio framework.
	nni_mtx		a_lk;
	nni_cv		a_cv;
	unsigned	a_flags;
	nni_taskq_ent	a_tqe;

	// Read/write operations.
	nni_iov		a_iov[4];
	int		a_niov;

	// Message operations.
	nni_msg *	a_msg;

	// TBD: Resolver operations.

	// Provider-use fields.
	void		(*a_prov_cancel)(nni_aio *);
	void *		a_prov_data;
	nni_list_node	a_prov_node;
};

// nni_aio_init initializes an aio object.  The callback is called with
// the supplied argument when the operation is complete.  If NULL is
// supplied for the callback, then nni_aio_wake is used in its place,
// and the aio is used for the argument.
extern int nni_aio_init(nni_aio *, nni_cb, void *);

// nni_aio_fini finalizes the aio, releasing resources (locks)
// associated with it.  The caller is responsible for ensuring that any
// associated I/O is unscheduled or complete.  This is safe to call
// on zero'd memory.
extern void nni_aio_fini(nni_aio *);

// nni_aio_result returns the result code (0 on success, or an NNG errno)
// for the operation.  It is only valid to call this when the operation is
// complete (such as when the callback is executed or after nni_aio_wait
// is performed).
extern int nni_aio_result(nni_aio *);

// nni_aio_count returns the number of bytes of data transferred, if any.
// As with nni_aio_result, it is only defined if the I/O operation has
// completed.
extern size_t nni_aio_count(nni_aio *);

// nni_aio_wake wakes any threads blocked in nni_aio_wait.  This is the
// default callback if no other is supplied.  If a user callback is supplied
// then that code must call this routine to wake any waiters (unless the
// user code is certain that there are no such waiters).
extern void nni_aio_wake(nni_aio *);

// nni_aio_wait blocks the caller until the operation is complete, as indicated
// by nni_aio_wake being called.  (Recall nni_aio_wake is the default
// callback if none is supplied.)  If a user supplied callback is provided,
// and that callback does not call nni_aio_wake, then this routine may
// block the caller indefinitely.
extern void nni_aio_wait(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).
extern void nni_aio_finish(nni_aio *, int, size_t);

extern int nni_aio_start(nni_aio *, void (*)(nni_aio *), void *);
extern void nni_aio_stop(nni_aio *);

#endif // CORE_AIO_H