From 314702f86c9199957e40edfb73bcdbddb422f9d7 Mon Sep 17 00:00:00 2001
From: Lukas Larsson
Date: Fri, 24 Feb 2017 19:38:37 +0100
Subject: erts: Add nif ioq
---
erts/doc/src/erl_nif.xml | 251 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 251 insertions(+)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 5a69bed34c..e47bb6a806 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -343,6 +343,81 @@ return term;
-
enif_convert_time_unit()
+
+ I/O Queues
+ -
+
The Erlang nif library contains function for easily working
+ with I/O vectors as used by the unix system call writev.
+ The I/O Queue is not thread safe, so some other synchronization
+ mechanism has to be used.
+
+ -
+ SysIOVec
+ -
+ ErlNifIOVec
+ -
+ enif_ioq_create()
+ -
+ enif_ioq_destroy()
+ -
+ enif_ioq_enq_binary()
+ -
+ enif_ioq_enqv()
+ -
+ enif_ioq_deq()
+ -
+ enif_ioq_peek()
+ -
+ enif_inspect_iovec()
+ -
+ enif_free_iovec()
+
+ Typical usage when writing to a file descriptor looks like this:
+ 0) {
+ /* If the I/O queue contains data we enqueue the iovec and
+ then peek the data to write out of the queue. */
+ if (!enif_ioq_enqv(q, iovec, 0))
+ return -3;
+
+ sysiovec = enif_ioq_peek(q, &iovcnt);
+ } else {
+ /* If the I/O queue is empty we skip the trip through it. */
+ iovcnt = iovec->iovcnt;
+ sysiovec = iovec->iov;
+ }
+
+ /* Attempt to write the data */
+ n = writev(fd, sysiovec, iovcnt);
+ saved_errno = errno;
+
+ if (enif_ioq_size(q) == 0) {
+ /* If the I/O queue was initially empty we enqueue any
+ remaining data into the queue for writing later. */
+ if (n >= 0 && !enif_ioq_enqv(q, iovec, n))
+ return -3;
+ } else {
+ /* Dequeue any data that was written from the queue. */
+ if (n > 0 && !enif_ioq_deq(q, n, NULL))
+ return -4;
+ }
+
+ /* return n, which is either number of bytes written or -1 if
+ some error happened */
+ errno = saved_errno;
+ return n;
+}]]>
Long-running NIFs
-
@@ -837,6 +912,36 @@ typedef enum {
+ SysIOVec
+ -
+
A system I/O vector, as used by writev on
+ Unix and WSASend on Win32. It is used in
+ ErlNifIOVec and by
+ enif_ioq_peek.
+
+ ErlNifIOVec
+ -
+
+typedef struct {
+ int iovcnt;
+ size_t size;
+ SysIOVec* iov;
+} ErlNifIOVec;
+ An I/O vector containing iovcnt SysIOVecs
+ pointing to the data. It is used by
+
+ enif_inspect_iovec and
+
+ enif_ioq_enqv.
+
+ ErlNifIOQueueOpts
+ -
+ Options to configure a ErlNifIOQueue.
+
+ ERL_NIF_IOQ_NORMAL
+
Create a normal I/O Queue
+
+
@@ -1142,6 +1247,31 @@ typedef enum {
+
+ void
+ enif_free_iovec(ErlNifIOvec* iov)
+ Free an ErlIOVec
+
+ Frees an io vector returned from
+
+ enif_inspect_iovec.
+ This is needed only if a NULL environment is passed to
+
+ enif_inspect_iovec.
+
+
+
+
intenif_get_atom(ErlNifEnv* env, ERL_NIF_TERM
term, char* buf, unsigned size, ErlNifCharEncoding encode)
@@ -1448,6 +1578,127 @@ typedef enum {
+
+ intenif_inspect_iovec(ErlNifEnv*
+ env, size_t max_elements, ERL_NIF_TERM iovec_term, ERL_NIF_TERM* tail,
+ ErlNifIOVec** iovec)
+ Inspect a list of binaries as an ErlNifIOVec.
+
+ Fills iovec with the list of binaries provided in
+ iovec_term. The number of elements handled in the call is
+ limited to max_elements, and tail is set to the
+ remainder of the list. Note that the output may be longer than
+ max_elements on some platforms.
+
+ To create a list of binaries from an arbitrary iolist, use
+
+ erlang:iolist_to_iovec/1.
+ When calling this function, iovec should contain a pointer to
+ NULL or a ErlNifIOVec structure that should be used if
+ possible. e.g.
+
+
+/* Don't use a pre-allocated structure */
+ErlNifIOVec *iovec = NULL;
+enif_inspect_iovec(env, max_elements, term, &tail, &iovec);
+
+/* Use a stack-allocated vector as an optimization for vectors with few elements */
+ErlNifIOVec vec, *iovec = &vec;
+enif_inspect_iovec(env, max_elements, term, &tail, &iovec);
+
+ The contents of the iovec is valid until the called nif
+ function returns. If the iovec should be valid after the nif
+ call returns, it is possible to call this function with a
+ NULL environment. If no environment is given the iovec
+ owns the data in the vector and it has to be explicitly freed using
+ enif_free_iovec
+ .
+ Returns true on success, or false if iovec_term
+ not an iovec.
+
+
+
+
+ ErlNifIOQueue *
+ enif_ioq_create(ErlNifIOQueueOpts opts)
+ Create a new IO Queue
+
+ Create a new I/O Queue that can be used to store data.
+ opts has to be set to ERL_NIF_IOQ_NORMAL.
+
+
+
+
+
+ void
+ enif_ioq_destroy(ErlNifIOQueue *q)
+ Destroy an IO Queue and free it's content
+
+ Destroy the I/O queue and free all of it's contents
+
+
+
+
+ int
+ enif_ioq_deq(ErlNifIOQueue *q, size_t count, size_t *size)
+ Dequeue count bytes from the IO Queue
+
+ Dequeue count bytes from the I/O queue.
+ If size is not NULL, the new size of the queue
+ is placed there.
+ Returns true on success, or false if the I/O does
+ not contain count bytes. On failure the queue is left un-altered.
+
+
+
+
+ int
+ enif_ioq_enq_binary(ErlNifIOQueue *q, ErlNifBinary *bin, size_t skip)
+ Enqueue the binary into the IO Queue
+
+ Enqueue the bin into q skipping the first skip bytes.
+ Returns true on success, or false if skip is greater
+ than the size of bin. Any ownership of the binary data is transferred
+ to the queue and bin is to be considered read-only for the rest of the NIF
+ call and then as released.
+
+
+
+
+ int
+ enif_ioq_enqv(ErlNifIOQueue *q, ErlNifIOVec *iovec, size_t skip)
+ Enqueue the iovec into the IO Queue
+
+ Enqueue the iovec into q skipping the first skip bytes.
+ Returns true on success, or false if skip is greater
+ than the size of iovec.
+
+
+
+
+ SysIOVec *
+ enif_ioq_peek(ErlNifIOQueue *q, int *iovlen)
+ Peek inside the IO Queue
+
+ Get the I/O queue as a pointer to an array of SysIOVecs.
+ It also returns the number of elements in iovlen.
+ This is the only way to get data out of the queue.
+ Nothing is removed from the queue by this function, that must be done
+ with enif_ioq_deq.
+ The returned array is suitable to use with the Unix system
+ call writev.
+
+
+
+
+ size_t
+ enif_ioq_size(ErlNifIOQueue *q)
+ Get the current size of the IO Queue
+
+ Get the size of q.
+
+
+
int
enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)
--
cgit v1.2.3
From eed25a02ba2416c48587699542aaecdd09609718 Mon Sep 17 00:00:00 2001
From: Lukas Larsson
Date: Tue, 5 Sep 2017 13:28:52 +0200
Subject: erts: Add erlang:iolist_to_iovec
OTP-14520
---
erts/doc/src/erlang.xml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
(limited to 'erts/doc')
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 105734d5b2..5ed7b92896 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -59,6 +59,14 @@
the Erlang external term format.
+
+ iovec()
+
+ A list of binaries. This datatype is useful to use
+ together with
+ enif_inspect_iovec.
+
+
@@ -2124,6 +2132,15 @@ os_prompt%
+
+
+ Converts an iolist to a iovec.
+
+ Returns an iovec that is made from the integers and binaries in
+ IoListOrBinary.
+
+
+
Check whether the local node is alive.
--
cgit v1.2.3