aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/erl_driver.xml2979
-rw-r--r--erts/doc/src/erl_nif.xml890
-rw-r--r--erts/doc/src/erl_tracer.xml263
-rw-r--r--erts/doc/src/erlang.xml476
-rw-r--r--erts/doc/src/zlib.xml429
5 files changed, 2765 insertions, 2272 deletions
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 82215ead46..d8116d4650 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -893,229 +893,26 @@ typedef struct ErlIOVec {
<funcs>
<func>
- <name><ret>void</ret><nametext>driver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size)</nametext></name>
- <fsummary>Get information about the Erlang runtime system</fsummary>
- <desc>
- <marker id="driver_system_info"></marker>
- <p>This function will write information about the Erlang runtime
- system into the
- <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
- structure referred to by the first argument. The second
- argument should be the size of the
- <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
- structure, i.e., <c>sizeof(ErlDrvSysInfo)</c>.</p>
- <p>See the documentation of the
- <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
- structure for information about specific fields.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len)</nametext></name>
- <fsummary>Send data from driver to port owner</fsummary>
- <desc>
- <marker id="driver_output"></marker>
- <p>The <c>driver_output</c> function is used to send data from
- the driver up to the emulator. The data will be received as
- terms or binary data, depending on how the driver port was
- opened.</p>
- <p>The data is queued in the port owner process' message
- queue. Note that this does not yield to the emulator. (Since
- the driver and the emulator run in the same thread.)</p>
- <p>The parameter <c>buf</c> points to the data to send, and
- <c>len</c> is the number of bytes.</p>
- <p>The return value for all output functions is 0. (Unless the
- driver is used for distribution, in which case it can fail
- and return -1. For normal use, the output function always
- returns 0.)</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len)</nametext></name>
- <fsummary>Send data and binary data to port owner</fsummary>
- <desc>
- <marker id="driver_output2"></marker>
- <p>The <c>driver_output2</c> function first sends <c>hbuf</c>
- (length in <c>hlen</c>) data as a list, regardless of port
- settings. Then <c>buf</c> is sent as a binary or list.
- E.g. if <c>hlen</c> is 3 then the port owner process will
- receive <c>[H1, H2, H3 | T]</c>.</p>
- <p>The point of sending data as a list header, is to facilitate
- matching on the data received.</p>
- <p>The return value is 0 for normal use.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
- <fsummary>Send data from a driver binary to port owner</fsummary>
- <desc>
- <marker id="driver_output_binary"></marker>
- <p>This function sends data to port owner process from a
- driver binary, it has a header buffer (<c>hbuf</c>
- and <c>hlen</c>) just like <c>driver_output2</c>. The
- <c>hbuf</c> parameter can be <c>NULL</c>.</p>
- <p>The parameter <c>offset</c> is an offset into the binary and
- <c>len</c> is the number of bytes to send.</p>
- <p>Driver binaries are created with <c>driver_alloc_binary</c>.</p>
- <p>The data in the header is sent as a list and the binary as
- an Erlang binary in the tail of the list.</p>
- <p>E.g. if <c>hlen</c> is 2, then the port owner process will
- receive <c><![CDATA[[H1, H2 | <<T>>]]]></c>.</p>
- <p>The return value is 0 for normal use.</p>
- <p>Note that, using the binary syntax in Erlang, the driver
- application can match the header directly from the binary,
- so the header can be put in the binary, and hlen can be set
- to 0.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
- <fsummary>Send vectorized data to port owner</fsummary>
- <desc>
- <marker id="driver_outputv"></marker>
- <p>This function sends data from an IO vector, <c>ev</c>, to
- the port owner process. It has a header buffer (<c>hbuf</c>
- and <c>hlen</c>), just like <c>driver_output2</c>.</p>
- <p>The <c>skip</c> parameter is a number of bytes to skip of
- the <c>ev</c> vector from the head.</p>
- <p>You get vectors of <c>ErlIOVec</c> type from the driver
- queue (see below), and the <seealso marker="driver_entry#outputv">outputv</seealso> driver entry
- function. You can also make them yourself, if you want to
- send several <c>ErlDrvBinary</c> buffers at once. Often
- it is faster to use <c>driver_output</c> or
- <c>driver_output_binary</c>.</p>
- <p>E.g. if <c>hlen</c> is 2 and <c>ev</c> points to an array of
- three binaries, the port owner process will receive <c><![CDATA[[H1, H2, <<B1>>, <<B2>> | <<B3>>]]]></c>.</p>
- <p>The return value is 0 for normal use.</p>
- <p>The comment for <c>driver_output_binary</c> applies for
- <c>driver_outputv</c> too.</p>
- </desc>
- </func>
- <func>
- <name><ret>ErlDrvSizeT</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len)</nametext></name>
- <fsummary>Collect data segments into a buffer</fsummary>
- <desc>
- <marker id="driver_vec_to_buf"></marker>
- <p>This function collects several segments of data, referenced
- by <c>ev</c>, by copying them in order to the buffer
- <c>buf</c>, of the size <c>len</c>.</p>
- <p>If the data is to be sent from the driver to the port owner
- process, it is faster to use <c>driver_outputv</c>.</p>
- <p>The return value is the space left in the buffer, i.e. if
- the <c>ev</c> contains less than <c>len</c> bytes it's the
- difference, and if <c>ev</c> contains <c>len</c> bytes or
- more, it's 0. This is faster if there is more than one header byte,
- since the binary syntax can construct integers directly from
- the binary.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_set_timer(ErlDrvPort port, unsigned long time)</nametext></name>
- <fsummary>Set a timer to call the driver</fsummary>
- <desc>
- <marker id="driver_set_timer"></marker>
- <p>This function sets a timer on the driver, which will count
- down and call the driver when it is timed out. The
- <c>time</c> parameter is the time in milliseconds before the
- timer expires.</p>
- <p>When the timer reaches 0 and expires, the driver entry
- function <seealso marker="driver_entry#timeout">timeout</seealso> is called.</p>
- <p>Note that there is only one timer on each driver instance;
- setting a new timer will replace an older one.</p>
- <p>Return value is 0 (-1 only when the <c>timeout</c> driver
- function is <c>NULL</c>).</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_cancel_timer(ErlDrvPort port)</nametext></name>
- <fsummary>Cancel a previously set timer</fsummary>
- <desc>
- <marker id="driver_cancel_timer"></marker>
- <p>This function cancels a timer set with
- <c>driver_set_timer</c>.</p>
- <p>The return value is 0.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_read_timer(ErlDrvPort port, unsigned long *time_left)</nametext></name>
- <fsummary>Read the time left before timeout</fsummary>
- <desc>
- <marker id="driver_read_timer"></marker>
- <p>This function reads the current time of a timer, and places
- the result in <c>time_left</c>. This is the time in
- milliseconds, before the timeout will occur.</p>
- <p>The return value is 0.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_get_now(ErlDrvNowData *now)</nametext></name>
- <fsummary>Read a system timestamp</fsummary>
- <desc>
- <marker id="driver_get_now"></marker>
- <warning><p><em>This function is deprecated! Do not use it!</em>
- Use <seealso marker="#erl_drv_monotonic_time"><c>erl_drv_monotonic_time()</c></seealso>
- (perhaps in combination with
- <seealso marker="#erl_drv_time_offset"><c>erl_drv_time_offset()</c></seealso>)
- instead.</p></warning>
- <p>This function reads a timestamp into the memory pointed to by
- the parameter <c>now</c>. See the description of <seealso marker="#ErlDrvNowData">ErlDrvNowData</seealso> for
- specification of its fields. </p>
- <p>The return value is 0 unless the <c>now</c> pointer is not
- valid, in which case it is &lt; 0. </p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on)</nametext></name>
- <fsummary>Provide an event for having the emulator call the driver</fsummary>
+ <name><ret>void</ret><nametext>add_driver_entry(ErlDrvEntry *de)</nametext></name>
+ <fsummary>Add a driver entry</fsummary>
<desc>
- <marker id="driver_select"></marker>
- <p>This function is used by drivers to provide the emulator with
- events to check for. This enables the emulator to call the driver
- when something has happened asynchronously.</p>
- <p>The <c>event</c> argument identifies an OS-specific event object.
- On Unix systems, the functions <c>select</c>/<c>poll</c> are used. The
- event object must be a socket or pipe (or other object that
- <c>select</c>/<c>poll</c> can use).
- On windows, the Win32 API function <c>WaitForMultipleObjects</c>
- is used. This places other restrictions on the event object.
- Refer to the Win32 SDK documentation.</p>
- <p>The <c>on</c> parameter should be <c>1</c> for setting events
- and <c>0</c> for clearing them.</p>
- <p>The <c>mode</c> argument is a bitwise-or combination of
- <c>ERL_DRV_READ</c>, <c>ERL_DRV_WRITE</c> and <c>ERL_DRV_USE</c>.
- The first two specify whether to wait for read events and/or write
- events. A fired read event will call
- <seealso marker="driver_entry#ready_input">ready_input</seealso>
- while a fired write event will call
- <seealso marker="driver_entry#ready_output">ready_output</seealso>.
- </p>
- <note>
- <p>Some OS (Windows) do not differentiate between read and write events.
- The call-back for a fired event then only depends on the value of <c>mode</c>.</p>
- </note>
- <p><c>ERL_DRV_USE</c> specifies if we are using the event object or if we want to close it.
- On an emulator with SMP support, it is not safe to clear all events
- and then close the event object after <c>driver_select</c> has
- returned. Another thread may still be using the event object
- internally. To safely close an event object call
- <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>. That
- will clear all events and then call
- <seealso marker="driver_entry#stop_select">stop_select</seealso>
- when it is safe to close the event object.
- <c>ERL_DRV_USE</c> should be set together with the first event
- for an event object. It is harmless to set <c>ERL_DRV_USE</c>
- even though it already has been done. Clearing all events but keeping
- <c>ERL_DRV_USE</c> set will indicate that we are using the event
- object and probably will set events for it again.</p>
- <note>
- <p>ERL_DRV_USE was added in OTP release R13. Old drivers will still work
- as before. But it is recommended to update them to use <c>ERL_DRV_USE</c> and
- <c>stop_select</c> to make sure that event objects are closed in a safe way.</p>
- </note>
- <p>The return value is 0 (failure, -1, only if the
- <c>ready_input</c>/<c>ready_output</c> is
- <c>NULL</c>).</p>
+ <marker id="add_driver_entry"></marker>
+ <p>This function adds a driver entry to the list of drivers
+ known by Erlang. The <seealso marker="driver_entry#init">init</seealso> function of the <c>de</c>
+ parameter is called.</p>
+ <note>
+ <p>To use this function for adding drivers residing in
+ dynamically loaded code is dangerous. If the driver code
+ for the added driver resides in the same dynamically
+ loaded module (i.e. <c>.so</c> file) as a normal
+ dynamically loaded driver (loaded with the <c>erl_ddll</c>
+ interface), the caller should call <seealso marker="#driver_lock_driver">driver_lock_driver</seealso> before
+ adding driver entries.</p>
+ <p>Use of this function is generally deprecated.</p>
+ </note>
</desc>
</func>
+
<func>
<name><ret>void *</ret><nametext>driver_alloc(ErlDrvSizeT size)</nametext></name>
<fsummary>Allocate memory</fsummary>
@@ -1130,32 +927,7 @@ typedef struct ErlIOVec {
<p>This function is thread-safe.</p>
</desc>
</func>
- <func>
- <name><ret>void *</ret><nametext>driver_realloc(void *ptr, ErlDrvSizeT size)</nametext></name>
- <fsummary>Resize an allocated memory block</fsummary>
- <desc>
- <marker id="driver_realloc"></marker>
- <p>This function resizes a memory block, either in place, or by
- allocating a new block, copying the data and freeing the old
- block. A pointer is returned to the reallocated memory. On
- failure (out of memory), <c>NULL</c> is returned. (This is
- most often a wrapper for <c>realloc</c>.)</p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>driver_free(void *ptr)</nametext></name>
- <fsummary>Free an allocated memory block</fsummary>
- <desc>
- <marker id="driver_free"></marker>
- <p>This function frees the memory pointed to by <c>ptr</c>. The
- memory should have been allocated with
- <c>driver_alloc</c>. All allocated memory should be
- deallocated, just once. There is no garbage collection in
- drivers.</p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
+
<func>
<name><ret>ErlDrvBinary *</ret><nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name>
<fsummary>Allocate a driver binary</fsummary>
@@ -1176,31 +948,114 @@ typedef struct ErlIOVec {
<p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvBinary *</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name>
- <fsummary>Resize a driver binary</fsummary>
+ <name><ret>long</ret><nametext>driver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*))</nametext></name>
+ <fsummary>Perform an asynchronous call within a driver</fsummary>
<desc>
- <marker id="driver_realloc_binary"></marker>
- <p>This function resizes a driver binary, while keeping the
- data. The resized driver binary is returned. On failure (out
- of memory), <c>NULL</c> is returned.</p>
- <p>This function is only thread-safe when the emulator with SMP
- support is used.</p>
+ <marker id="driver_async"></marker>
+ <p>This function performs an asynchronous call. The function
+ <c>async_invoke</c> is invoked in a thread separate from the
+ emulator thread. This enables the driver to perform
+ time-consuming, blocking operations without blocking the
+ emulator.</p>
+ <p>The async thread pool size can be set with the
+ <seealso marker="erl#async_thread_pool_size">+A</seealso>
+ command line argument of <seealso marker="erl">erl(1)</seealso>.
+ If no async thread pool is available, the call is made
+ synchronously in the thread calling <c>driver_async()</c>. The
+ current number of async threads in the async thread pool can be
+ retrieved via
+ <seealso marker="#driver_system_info">driver_system_info()</seealso>.</p>
+ <p>If there is a thread pool available, a thread will be
+ used. If the <c>key</c> argument is null, the threads from the
+ pool are used in a round-robin way, each call to
+ <c>driver_async</c> uses the next thread in the pool. With the
+ <c>key</c> argument set, this behaviour is changed. The two
+ same values of <c>*key</c> always get the same thread.</p>
+ <p>To make sure that a driver instance always uses the same
+ thread, the following call can be used:</p>
+ <p></p>
+ <code type="none"><![CDATA[
+ unsigned int myKey = driver_async_port_key(myPort);
+
+ r = driver_async(myPort, &myKey, myData, myFunc);
+ ]]></code>
+ <p>It is enough to initialize <c>myKey</c> once for each
+ driver instance.</p>
+ <p>If a thread is already working, the calls will be
+ queued up and executed in order. Using the same thread for
+ each driver instance ensures that the calls will be made in
+ sequence.</p>
+ <p>The <c>async_data</c> is the argument to the functions
+ <c>async_invoke</c> and <c>async_free</c>. It's typically a
+ pointer to a structure that contains a pipe or event that
+ can be used to signal that the async operation completed.
+ The data should be freed in <c>async_free</c>.</p>
+ <p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver
+ entry function is called. If <c>ready_async</c> is null in
+ the driver entry, the <c>async_free</c> function is called
+ instead.</p>
+ <p>The return value is -1 if the <c>driver_async</c> call
+ fails.</p>
+ <note>
+ <p>As of erts version 5.5.4.3 the default stack size for
+ threads in the async-thread pool is 16 kilowords,
+ i.e., 64 kilobyte on 32-bit architectures.
+ This small default size has been chosen since the
+ amount of async-threads might be quite large. The
+ default stack size is enough for drivers delivered
+ with Erlang/OTP, but might not be sufficiently large
+ for other dynamically linked in drivers that use the
+ driver_async() functionality. A suggested stack size
+ for threads in the async-thread pool can be configured
+ via the
+ <seealso marker="erl#async_thread_stack_size">+a</seealso>
+ command line argument of
+ <seealso marker="erl">erl(1)</seealso>.</p>
+ </note>
+ </desc>
+ </func>
+<func>
+ <name><ret>unsigned int</ret><nametext>driver_async_port_key (ErlDrvPort port)</nametext></name>
+ <fsummary>Calculate an async key from an ErlDrvPort</fsummary>
+ <desc>
+ <marker id="driver_async_port_key"></marker>
+ <p>This function calculates a key for later use in <seealso
+ marker="#driver_async">driver_async()</seealso>. The keys are
+ evenly distributed so that a fair mapping between port id's
+ and async thread id's is achieved.</p>
+ <note>
+ <p>Before OTP-R16, the actual port id could be used as a key
+ with proper casting, but after the rewrite of the port
+ subsystem, this is no longer the case. With this function, you
+ can achieve the same distribution based on port id's as before
+ OTP-R16.</p>
+ </note>
</desc>
</func>
+
<func>
- <name><ret>void</ret><nametext>driver_free_binary(ErlDrvBinary *bin)</nametext></name>
- <fsummary>Free a driver binary</fsummary>
+ <name><ret>long</ret><nametext>driver_binary_dec_refc(ErlDrvBinary *bin)</nametext></name>
+ <fsummary>Decrement the reference count of a driver binary</fsummary>
<desc>
- <marker id="driver_free_binary"></marker>
- <p>This function frees a driver binary <c>bin</c>, allocated
- previously with <c>driver_alloc_binary</c>. Since binaries
- in Erlang are reference counted, the binary may still be
- around.</p>
+ <marker id="driver_binary_dec_refc"></marker>
+ <p>Decrements the reference count on <c>bin</c> and returns
+ the reference count reached after the decrement.</p>
<p>This function is only thread-safe when the emulator with SMP
support is used.</p>
+ <note>
+ <p>You should normally decrement the reference count of a
+ driver binary by calling
+ <seealso marker="#driver_free_binary">driver_free_binary()</seealso>.
+ <c>driver_binary_dec_refc()</c> does <em>not</em> free
+ the binary if the reference count reaches zero. <em>Only</em>
+ use <c>driver_binary_dec_refc()</c> when you are sure
+ <em>not</em> to reach a reference count of zero.</p>
+ </note>
</desc>
</func>
+
<func>
<name><ret>long</ret><nametext>driver_binary_get_refc(ErlDrvBinary *bin)</nametext></name>
<fsummary>Get the reference count of a driver binary</fsummary>
@@ -1211,6 +1066,7 @@ typedef struct ErlIOVec {
support is used.</p>
</desc>
</func>
+
<func>
<name><ret>long</ret><nametext>driver_binary_inc_refc(ErlDrvBinary *bin)</nametext></name>
<fsummary>Increment the reference count of a driver binary</fsummary>
@@ -1222,65 +1078,134 @@ typedef struct ErlIOVec {
support is used.</p>
</desc>
</func>
+
<func>
- <name><ret>long</ret><nametext>driver_binary_dec_refc(ErlDrvBinary *bin)</nametext></name>
- <fsummary>Decrement the reference count of a driver binary</fsummary>
+ <name><ret>ErlDrvTermData</ret><nametext>driver_caller(ErlDrvPort port)</nametext></name>
+ <fsummary>Return the process making the driver call</fsummary>
<desc>
- <marker id="driver_binary_dec_refc"></marker>
- <p>Decrements the reference count on <c>bin</c> and returns
- the reference count reached after the decrement.</p>
- <p>This function is only thread-safe when the emulator with SMP
- support is used.</p>
- <note>
- <p>You should normally decrement the reference count of a
- driver binary by calling
- <seealso marker="#driver_free_binary">driver_free_binary()</seealso>.
- <c>driver_binary_dec_refc()</c> does <em>not</em> free
- the binary if the reference count reaches zero. <em>Only</em>
- use <c>driver_binary_dec_refc()</c> when you are sure
- <em>not</em> to reach a reference count of zero.</p>
- </note>
+ <marker id="driver_caller"></marker>
+ <p>This function returns the process id of the process that
+ made the current call to the driver. The process id can be
+ used with <c>driver_send_term</c> to send back data to the
+ caller. <c>driver_caller()</c> only returns valid data
+ when currently executing in one of the following driver
+ callbacks:</p>
+ <taglist>
+ <tag><seealso marker="driver_entry#start">start</seealso></tag>
+ <item>Called from <c>open_port/2</c>.</item>
+ <tag><seealso marker="driver_entry#output">output</seealso></tag>
+ <item>Called from <c>erlang:send/2</c>, and
+ <c>erlang:port_command/2</c></item>
+ <tag><seealso marker="driver_entry#outputv">outputv</seealso></tag>
+ <item>Called from <c>erlang:send/2</c>, and
+ <c>erlang:port_command/2</c></item>
+ <tag><seealso marker="driver_entry#control">control</seealso></tag>
+ <item>Called from <c>erlang:port_control/3</c></item>
+ <tag><seealso marker="driver_entry#call">call</seealso></tag>
+ <item>Called from <c>erlang:port_call/3</c></item>
+ </taglist>
+ <p>Note that this function is <em>not</em> thread-safe, not
+ even when the emulator with SMP support is used.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
- <fsummary>Enqueue data in the driver queue</fsummary>
+ <name><ret>int</ret><nametext>driver_cancel_timer(ErlDrvPort port)</nametext></name>
+ <fsummary>Cancel a previously set timer</fsummary>
<desc>
- <marker id="driver_enq"></marker>
- <p>This function enqueues data in the driver queue. The data in
- <c>buf</c> is copied (<c>len</c> bytes) and placed at the
- end of the driver queue. The driver queue is normally used
- in a FIFO way.</p>
- <p>The driver queue is available to queue output from the
- emulator to the driver (data from the driver to the emulator
- is queued by the emulator in normal erlang message
- queues). This can be useful if the driver has to wait for
- slow devices etc, and wants to yield back to the
- emulator. The driver queue is implemented as an ErlIOVec.</p>
- <p>When the queue contains data, the driver won't close, until
- the queue is empty.</p>
+ <marker id="driver_cancel_timer"></marker>
+ <p>This function cancels a timer set with
+ <c>driver_set_timer</c>.</p>
<p>The return value is 0.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
- <fsummary>Push data at the head of the driver queue</fsummary>
+ <name><ret>int</ret><nametext>driver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2)</nametext></name>
+ <fsummary>Compare two monitors</fsummary>
<desc>
- <marker id="driver_pushq"></marker>
- <p>This function puts data at the head of the driver queue. The
- data in <c>buf</c> is copied (<c>len</c> bytes) and placed
- at the beginning of the queue.</p>
- <p>The return value is 0.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
+ <marker id="driver_compare_monitors"></marker>
+ <p>This function is used to compare two <c>ErlDrvMonitor</c>s. It
+ can also be used to imply some artificial order on monitors,
+ for whatever reason.</p>
+ <p>The function returns 0 if <c>monitor1</c> and
+ <c>monitor2</c> are equal, &lt; 0 if <c>monitor1</c> is less
+ than <c>monitor2</c> and &gt; 0 if <c>monitor1</c> is greater
+ than <c>monitor2</c>.</p>
</desc>
</func>
+
+ <func>
+ <name><ret>ErlDrvTermData</ret><nametext>driver_connected(ErlDrvPort port)</nametext></name>
+ <fsummary>Return the port owner process</fsummary>
+ <desc>
+ <marker id="driver_connected"></marker>
+ <p>This function returns the port owner process.</p>
+ <p>Note that this function is <em>not</em> thread-safe, not
+ even when the emulator with SMP support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvPort</ret><nametext>driver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data)</nametext></name>
+ <fsummary>Create a new port (driver instance)</fsummary>
+ <desc>
+ <p>This function creates a new port executing the same driver
+ code as the port creating the new port.
+ A short description of the arguments:</p>
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>The port handle of the port (driver instance) creating
+ the new port.</item>
+ <tag><c>owner_pid</c></tag>
+ <item>The process id of the Erlang process which will be
+ owner of the new port. This process will be linked
+ to the new port. You usually want to use
+ <c>driver_caller(port)</c> as <c>owner_pid</c>.</item>
+ <tag><c>name</c></tag>
+ <item>The port name of the new port. You usually want to
+ use the same port name as the driver name
+ (<seealso marker="driver_entry#driver_name">driver_name</seealso>
+ field of the
+ <seealso marker="driver_entry">driver_entry</seealso>).</item>
+ <tag><c>drv_data</c></tag>
+ <item>The driver defined handle that will be passed in subsequent
+ calls to driver call-backs. Note, that the
+ <seealso marker="driver_entry#start">driver start call-back</seealso>
+ will not be called for this new driver instance.
+ The driver defined handle is normally created in the
+ <seealso marker="driver_entry#start">driver start call-back</seealso>
+ when a port is created via
+ <seealso marker="erlang#open_port/2">erlang:open_port/2</seealso>. </item>
+ </taglist>
+ <p>The caller of <c>driver_create_port()</c> is allowed to
+ manipulate the newly created port when <c>driver_create_port()</c>
+ has returned. When
+ <seealso marker="#smp_support">port level locking</seealso>
+ is used, the creating port is, however, only allowed to
+ manipulate the newly created port until the current driver
+ call-back that was called by the emulator returns.</p>
+ <note>
+ <p>When
+ <seealso marker="#smp_support">port level locking</seealso>
+ is used, the creating port is only allowed to manipulate
+ the newly created port until the current driver call-back
+ returns.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name>
+ <fsummary>Stop monitoring a process from a driver</fsummary>
+ <desc>
+ <marker id="driver_demonitor_process"></marker>
+ <p>This function cancels a monitor created earlier. </p>
+ <p>The function returns 0 if a monitor was removed and &gt; 0
+ if the monitor did no longer exist.</p>
+ </desc>
+ </func>
+
<func>
<name><ret>ErlDrvSizeT</ret><nametext>driver_deq(ErlDrvPort port, ErlDrvSizeT size)</nametext></name>
<fsummary>Dequeue data from the head of the driver queue</fsummary>
@@ -1297,19 +1222,32 @@ typedef struct ErlIOVec {
thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvSizeT</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name>
- <fsummary>Return the size of the driver queue</fsummary>
+ <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Enqueue data in the driver queue</fsummary>
<desc>
- <marker id="driver_sizeq"></marker>
- <p>This function returns the number of bytes currently in the
- driver queue.</p>
+ <marker id="driver_enq"></marker>
+ <p>This function enqueues data in the driver queue. The data in
+ <c>buf</c> is copied (<c>len</c> bytes) and placed at the
+ end of the driver queue. The driver queue is normally used
+ in a FIFO way.</p>
+ <p>The driver queue is available to queue output from the
+ emulator to the driver (data from the driver to the emulator
+ is queued by the emulator in normal erlang message
+ queues). This can be useful if the driver has to wait for
+ slow devices etc, and wants to yield back to the
+ emulator. The driver queue is implemented as an ErlIOVec.</p>
+ <p>When the queue contains data, the driver won't close, until
+ the queue is empty.</p>
+ <p>The return value is 0.</p>
<p>This function can be called from an arbitrary thread if a
<seealso marker="#ErlDrvPDL">port data lock</seealso>
associated with the <c>port</c> is locked by the calling
thread during the call.</p>
</desc>
</func>
+
<func>
<name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
<fsummary>Enqueue binary in the driver queue</fsummary>
@@ -1327,96 +1265,280 @@ typedef struct ErlIOVec {
<p>The return value is 0.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
- <fsummary>Push binary at the head of the driver queue</fsummary>
+ <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
+ <fsummary>Enqueue vector in the driver queue</fsummary>
<desc>
- <marker id="driver_pushq_bin"></marker>
- <p>This function puts data in the binary <c>bin</c>, at
- <c>offset</c> with length <c>len</c> at the head of the
- driver queue. It is most often faster than
- <c>driver_pushq</c>, because the data doesn't have to be
- copied.</p>
+ <marker id="driver_enqv"></marker>
+ <p>This function enqueues the data in <c>ev</c>, skipping the
+ first <c>skip</c> bytes of it, at the end of the driver
+ queue. It is faster than <c>driver_enq</c>, because the data
+ doesn't have to be copied.</p>
+ <p>The return value is 0.</p>
<p>This function can be called from an arbitrary thread if a
<seealso marker="#ErlDrvPDL">port data lock</seealso>
associated with the <c>port</c> is locked by the calling
thread during the call.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_failure_atom(ErlDrvPort port, char *string)</nametext></name>
+ <name><ret>int</ret><nametext>driver_failure_posix(ErlDrvPort port, int error)</nametext></name>
+ <name><ret>int</ret><nametext>driver_failure(ErlDrvPort port, int error)</nametext></name>
+ <fsummary>Fail with error</fsummary>
+ <desc>
+ <marker id="driver_failure_atom"></marker>
+ <marker id="driver_failure_posix"></marker>
+ <marker id="driver_failure"></marker>
+ <p>These functions signal to Erlang that the driver has
+ encountered an error and should be closed. The port is
+ closed and the tuple <c>{'EXIT', error, Err}</c>, is sent to
+ the port owner process, where error is an error atom
+ (<c>driver_failure_atom</c> and
+ <c>driver_failure_posix</c>), or an integer
+ (<c>driver_failure</c>).</p>
+ <p>The driver should fail only when in severe error situations,
+ when the driver cannot possibly keep open, for instance
+ buffer allocation gets out of memory. For normal errors
+ it is more appropriate to send error codes with
+ <c>driver_output</c>.</p>
<p>The return value is 0.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvSizeT</ret><nametext>driver_peekqv(ErlDrvPort port, ErlIOVec *ev)</nametext></name>
- <fsummary>Get the driver queue as an IO vector</fsummary>
+ <name><ret>int</ret><nametext>driver_failure_eof(ErlDrvPort port)</nametext></name>
+ <fsummary>Fail with EOF</fsummary>
<desc>
- <marker id="driver_peekqv"></marker>
- <p>
- This function retrieves the driver queue into a supplied
- <c>ErlIOVec</c> <c>ev</c>. It also returns the queue size.
- This is one of two ways to get data out of the queue.
- </p>
- <p>
- If <c>ev</c> is <c>NULL</c> all ones i.e. <c>-1</c> type cast to
- <c>ErlDrvSizeT</c> is returned.
- </p>
- <p>Nothing is removed from the queue by this function, that must be done
- with <c>driver_deq</c>.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
+ <marker id="driver_failure_eof"></marker>
+ <p>This function signals to erlang that the driver has
+ encountered an EOF and should be closed, unless the port was
+ opened with the <c>eof</c> option, in that case eof is sent
+ to the port. Otherwise, the port is closed and an
+ <c>'EXIT'</c> message is sent to the port owner process.</p>
+ <p>The return value is 0.</p>
</desc>
</func>
+
<func>
- <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name>
- <fsummary>Get the driver queue as a vector</fsummary>
+ <name><ret>void</ret><nametext>driver_free(void *ptr)</nametext></name>
+ <fsummary>Free an allocated memory block</fsummary>
<desc>
- <marker id="driver_peekq"></marker>
- <p>This function retrieves the driver queue as a pointer to an
- array of <c>SysIOVec</c>s. It also returns the number of
- elements in <c>vlen</c>. This is one of two ways to get data
- out of the queue.</p>
- <p>Nothing is removed from the queue by this function, that must be done
- with <c>driver_deq</c>.</p>
- <p>The returned array is suitable to use with the Unix system
- call <c>writev</c>.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
+ <marker id="driver_free"></marker>
+ <p>This function frees the memory pointed to by <c>ptr</c>. The
+ memory should have been allocated with
+ <c>driver_alloc</c>. All allocated memory should be
+ deallocated, just once. There is no garbage collection in
+ drivers.</p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
- <fsummary>Enqueue vector in the driver queue</fsummary>
+ <name><ret>void</ret><nametext>driver_free_binary(ErlDrvBinary *bin)</nametext></name>
+ <fsummary>Free a driver binary</fsummary>
<desc>
- <marker id="driver_enqv"></marker>
- <p>This function enqueues the data in <c>ev</c>, skipping the
- first <c>skip</c> bytes of it, at the end of the driver
- queue. It is faster than <c>driver_enq</c>, because the data
- doesn't have to be copied.</p>
- <p>The return value is 0.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
+ <marker id="driver_free_binary"></marker>
+ <p>This function frees a driver binary <c>bin</c>, allocated
+ previously with <c>driver_alloc_binary</c>. Since binaries
+ in Erlang are reference counted, the binary may still be
+ around.</p>
+ <p>This function is only thread-safe when the emulator with SMP
+ support is used.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
- <fsummary>Push vector at the head of the driver queue</fsummary>
+ <name><ret>ErlDrvTermData</ret><nametext>driver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name>
+ <fsummary>Retrieve the process id from a monitor</fsummary>
<desc>
- <marker id="driver_pushqv"></marker>
- <p>This function puts the data in <c>ev</c>, skipping the first
- <c>skip</c> bytes of it, at the head of the driver queue.
- It is faster than <c>driver_pushq</c>, because the data
- doesn't have to be copied.</p>
- <p>The return value is 0.</p>
- <p>This function can be called from an arbitrary thread if a
- <seealso marker="#ErlDrvPDL">port data lock</seealso>
- associated with the <c>port</c> is locked by the calling
- thread during the call.</p>
+ <marker id="driver_get_monitored_process"></marker>
+ <p>The function returns the process id associated with a living
+ monitor. It can be used in the <c>process_exit</c> call-back to
+ get the process identification for the exiting process.</p>
+ <p>The function returns <c>driver_term_nil</c> if the monitor
+ no longer exists.</p>
</desc>
</func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_get_now(ErlDrvNowData *now)</nametext></name>
+ <fsummary>Read a system timestamp</fsummary>
+ <desc>
+ <marker id="driver_get_now"></marker>
+ <warning><p><em>This function is deprecated! Do not use it!</em>
+ Use <seealso marker="#erl_drv_monotonic_time"><c>erl_drv_monotonic_time()</c></seealso>
+ (perhaps in combination with
+ <seealso marker="#erl_drv_time_offset"><c>erl_drv_time_offset()</c></seealso>)
+ instead.</p></warning>
+ <p>This function reads a timestamp into the memory pointed to by
+ the parameter <c>now</c>. See the description of <seealso marker="#ErlDrvNowData">ErlDrvNowData</seealso> for
+ specification of its fields. </p>
+ <p>The return value is 0 unless the <c>now</c> pointer is not
+ valid, in which case it is &lt; 0. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_lock_driver(ErlDrvPort port)</nametext></name>
+ <fsummary>Make sure the driver is never unloaded</fsummary>
+ <desc>
+ <marker id="driver_lock_driver"></marker>
+ <p>This function locks the driver used by the port <c>port</c>
+ in memory for the rest of the emulator process'
+ lifetime. After this call, the driver behaves as one of Erlang's
+ statically linked in drivers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvTermData</ret><nametext>driver_mk_atom(char* string)</nametext></name>
+ <fsummary>Make an atom from a name</fsummary>
+ <desc>
+ <marker id="driver_mk_atom"></marker>
+ <p>This function returns an atom given a name
+ <c>string</c>. The atom is created and won't change, so the
+ return value may be saved and reused, which is faster than
+ looking up the atom several times.</p>
+ <p>Note that this function is <em>not</em> thread-safe, not
+ even when the emulator with SMP support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvTermData</ret><nametext>driver_mk_port(ErlDrvPort port)</nametext></name>
+ <fsummary>Make a erlang term port from a port</fsummary>
+ <desc>
+ <marker id="driver_mk_port"></marker>
+ <p>This function converts a port handle to the erlang term
+ format, usable in the <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>, and <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> functions.</p>
+ <p>Note that this function is <em>not</em> thread-safe, not
+ even when the emulator with SMP support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_monitor_process(ErlDrvPort port, ErlDrvTermData process, ErlDrvMonitor *monitor)</nametext></name>
+ <fsummary>Monitor a process from a driver</fsummary>
+ <desc>
+ <marker id="driver_monitor_process"></marker>
+ <p>Start monitoring a process from a driver. When a process is
+ monitored, a process exit will result in a call to the
+ provided <seealso marker="driver_entry#process_exit">process_exit</seealso> call-back
+ in the <seealso marker="driver_entry">ErlDrvEntry</seealso>
+ structure. The <c>ErlDrvMonitor</c> structure is filled in, for later
+ removal or compare.</p>
+ <p>The <c>process</c> parameter should be the return value of an
+ earlier call to <seealso marker="#driver_caller">driver_caller</seealso> or <seealso marker="#driver_connected">driver_connected</seealso> call.</p>
+ <p>The function returns 0 on success, &lt; 0 if no call-back is
+ provided and &gt; 0 if the process is no longer alive.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Send data from driver to port owner</fsummary>
+ <desc>
+ <marker id="driver_output"></marker>
+ <p>The <c>driver_output</c> function is used to send data from
+ the driver up to the emulator. The data will be received as
+ terms or binary data, depending on how the driver port was
+ opened.</p>
+ <p>The data is queued in the port owner process' message
+ queue. Note that this does not yield to the emulator. (Since
+ the driver and the emulator run in the same thread.)</p>
+ <p>The parameter <c>buf</c> points to the data to send, and
+ <c>len</c> is the number of bytes.</p>
+ <p>The return value for all output functions is 0. (Unless the
+ driver is used for distribution, in which case it can fail
+ and return -1. For normal use, the output function always
+ returns 0.)</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Send data from a driver binary to port owner</fsummary>
+ <desc>
+ <marker id="driver_output_binary"></marker>
+ <p>This function sends data to port owner process from a
+ driver binary, it has a header buffer (<c>hbuf</c>
+ and <c>hlen</c>) just like <c>driver_output2</c>. The
+ <c>hbuf</c> parameter can be <c>NULL</c>.</p>
+ <p>The parameter <c>offset</c> is an offset into the binary and
+ <c>len</c> is the number of bytes to send.</p>
+ <p>Driver binaries are created with <c>driver_alloc_binary</c>.</p>
+ <p>The data in the header is sent as a list and the binary as
+ an Erlang binary in the tail of the list.</p>
+ <p>E.g. if <c>hlen</c> is 2, then the port owner process will
+ receive <c><![CDATA[[H1, H2 | <<T>>]]]></c>.</p>
+ <p>The return value is 0 for normal use.</p>
+ <p>Note that, using the binary syntax in Erlang, the driver
+ application can match the header directly from the binary,
+ so the header can be put in the binary, and hlen can be set
+ to 0.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n)</nametext></name>
+ <fsummary>Send term data from driver to port owner</fsummary>
+ <desc>
+ <marker id="driver_output_term"></marker>
+ <warning><p><c>driver_output_term()</c> is deprecated and will
+ be removed in the OTP-R17 release. Use
+ <seealso marker="#erl_drv_send_term">erl_drv_output_term()</seealso>
+ instead.</p>
+ </warning>
+ <p>The parameters <c>term</c> and <c>n</c> do the same thing
+ as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
+ <p>Note that this function is <em>not</em> thread-safe, not
+ even when the emulator with SMP support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Send data and binary data to port owner</fsummary>
+ <desc>
+ <marker id="driver_output2"></marker>
+ <p>The <c>driver_output2</c> function first sends <c>hbuf</c>
+ (length in <c>hlen</c>) data as a list, regardless of port
+ settings. Then <c>buf</c> is sent as a binary or list.
+ E.g. if <c>hlen</c> is 3 then the port owner process will
+ receive <c>[H1, H2, H3 | T]</c>.</p>
+ <p>The point of sending data as a list header, is to facilitate
+ matching on the data received.</p>
+ <p>The return value is 0 for normal use.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
+ <fsummary>Send vectorized data to port owner</fsummary>
+ <desc>
+ <marker id="driver_outputv"></marker>
+ <p>This function sends data from an IO vector, <c>ev</c>, to
+ the port owner process. It has a header buffer (<c>hbuf</c>
+ and <c>hlen</c>), just like <c>driver_output2</c>.</p>
+ <p>The <c>skip</c> parameter is a number of bytes to skip of
+ the <c>ev</c> vector from the head.</p>
+ <p>You get vectors of <c>ErlIOVec</c> type from the driver
+ queue (see below), and the <seealso marker="driver_entry#outputv">outputv</seealso> driver entry
+ function. You can also make them yourself, if you want to
+ send several <c>ErlDrvBinary</c> buffers at once. Often
+ it is faster to use <c>driver_output</c> or
+ <c>driver_output_binary</c>.</p>
+ <p>E.g. if <c>hlen</c> is 2 and <c>ev</c> points to an array of
+ three binaries, the port owner process will receive <c><![CDATA[[H1, H2, <<B1>>, <<B2>> | <<B3>>]]]></c>.</p>
+ <p>The return value is 0 for normal use.</p>
+ <p>The comment for <c>driver_output_binary</c> applies for
+ <c>driver_outputv</c> too.</p>
+ </desc>
+ </func>
+
<func>
<name><ret>ErlDrvPDL</ret><nametext>driver_pdl_create(ErlDrvPort port)</nametext></name>
<fsummary>Create a port data lock</fsummary>
@@ -1432,26 +1554,20 @@ typedef struct ErlIOVec {
been associated with the <c>port</c>.</p>
</desc>
</func>
+
<func>
- <name><ret>void</ret><nametext>driver_pdl_lock(ErlDrvPDL pdl)</nametext></name>
- <fsummary>Lock port data lock</fsummary>
- <desc>
- <marker id="driver_pdl_lock"></marker>
- <p>This function locks the port data lock passed as argument
- (<c>pdl</c>).</p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>driver_pdl_unlock(ErlDrvPDL pdl)</nametext></name>
- <fsummary>Unlock port data lock</fsummary>
+ <name><ret>long</ret><nametext>driver_pdl_dec_refc(ErlDrvPDL pdl)</nametext></name>
+ <fsummary></fsummary>
<desc>
- <marker id="driver_pdl_unlock"></marker>
- <p>This function unlocks the port data lock passed as argument
- (<c>pdl</c>).</p>
+ <marker id="driver_pdl_dec_refc"></marker>
+ <p>This function decrements the reference count of
+ the port data lock passed as argument (<c>pdl</c>).</p>
+ <p>The current reference count after the decrement has
+ been performed is returned.</p>
<p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
<name><ret>long</ret><nametext>driver_pdl_get_refc(ErlDrvPDL pdl)</nametext></name>
<fsummary></fsummary>
@@ -1462,6 +1578,7 @@ typedef struct ErlIOVec {
<p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
<name><ret>long</ret><nametext>driver_pdl_inc_refc(ErlDrvPDL pdl)</nametext></name>
<fsummary></fsummary>
@@ -1474,113 +1591,306 @@ typedef struct ErlIOVec {
<p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>long</ret><nametext>driver_pdl_dec_refc(ErlDrvPDL pdl)</nametext></name>
- <fsummary></fsummary>
+ <name><ret>void</ret><nametext>driver_pdl_lock(ErlDrvPDL pdl)</nametext></name>
+ <fsummary>Lock port data lock</fsummary>
<desc>
- <marker id="driver_pdl_dec_refc"></marker>
- <p>This function decrements the reference count of
- the port data lock passed as argument (<c>pdl</c>).</p>
- <p>The current reference count after the decrement has
- been performed is returned.</p>
+ <marker id="driver_pdl_lock"></marker>
+ <p>This function locks the port data lock passed as argument
+ (<c>pdl</c>).</p>
<p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_monitor_process(ErlDrvPort port, ErlDrvTermData process, ErlDrvMonitor *monitor)</nametext></name>
- <fsummary>Monitor a process from a driver</fsummary>
+ <name><ret>void</ret><nametext>driver_pdl_unlock(ErlDrvPDL pdl)</nametext></name>
+ <fsummary>Unlock port data lock</fsummary>
<desc>
- <marker id="driver_monitor_process"></marker>
- <p>Start monitoring a process from a driver. When a process is
- monitored, a process exit will result in a call to the
- provided <seealso marker="driver_entry#process_exit">process_exit</seealso> call-back
- in the <seealso marker="driver_entry">ErlDrvEntry</seealso>
- structure. The <c>ErlDrvMonitor</c> structure is filled in, for later
- removal or compare.</p>
- <p>The <c>process</c> parameter should be the return value of an
- earlier call to <seealso marker="#driver_caller">driver_caller</seealso> or <seealso marker="#driver_connected">driver_connected</seealso> call.</p>
- <p>The function returns 0 on success, &lt; 0 if no call-back is
- provided and &gt; 0 if the process is no longer alive.</p>
+ <marker id="driver_pdl_unlock"></marker>
+ <p>This function unlocks the port data lock passed as argument
+ (<c>pdl</c>).</p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name>
- <fsummary>Stop monitoring a process from a driver</fsummary>
+ <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name>
+ <fsummary>Get the driver queue as a vector</fsummary>
<desc>
- <marker id="driver_demonitor_process"></marker>
- <p>This function cancels a monitor created earlier. </p>
- <p>The function returns 0 if a monitor was removed and &gt; 0
- if the monitor did no longer exist.</p>
+ <marker id="driver_peekq"></marker>
+ <p>This function retrieves the driver queue as a pointer to an
+ array of <c>SysIOVec</c>s. It also returns the number of
+ elements in <c>vlen</c>. This is one of two ways to get data
+ out of the queue.</p>
+ <p>Nothing is removed from the queue by this function, that must be done
+ with <c>driver_deq</c>.</p>
+ <p>The returned array is suitable to use with the Unix system
+ call <c>writev</c>.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvTermData</ret><nametext>driver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name>
- <fsummary>Retrieve the process id from a monitor</fsummary>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_peekqv(ErlDrvPort port, ErlIOVec *ev)</nametext></name>
+ <fsummary>Get the driver queue as an IO vector</fsummary>
<desc>
- <marker id="driver_get_monitored_process"></marker>
- <p>The function returns the process id associated with a living
- monitor. It can be used in the <c>process_exit</c> call-back to
- get the process identification for the exiting process.</p>
- <p>The function returns <c>driver_term_nil</c> if the monitor
- no longer exists.</p>
+ <marker id="driver_peekqv"></marker>
+ <p>
+ This function retrieves the driver queue into a supplied
+ <c>ErlIOVec</c> <c>ev</c>. It also returns the queue size.
+ This is one of two ways to get data out of the queue.
+ </p>
+ <p>
+ If <c>ev</c> is <c>NULL</c> all ones i.e. <c>-1</c> type cast to
+ <c>ErlDrvSizeT</c> is returned.
+ </p>
+ <p>Nothing is removed from the queue by this function, that must be done
+ with <c>driver_deq</c>.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2)</nametext></name>
- <fsummary>Compare two monitors</fsummary>
+ <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Push data at the head of the driver queue</fsummary>
<desc>
- <marker id="driver_compare_monitors"></marker>
- <p>This function is used to compare two <c>ErlDrvMonitor</c>s. It
- can also be used to imply some artificial order on monitors,
- for whatever reason.</p>
- <p>The function returns 0 if <c>monitor1</c> and
- <c>monitor2</c> are equal, &lt; 0 if <c>monitor1</c> is less
- than <c>monitor2</c> and &gt; 0 if <c>monitor1</c> is greater
- than <c>monitor2</c>.</p>
+ <marker id="driver_pushq"></marker>
+ <p>This function puts data at the head of the driver queue. The
+ data in <c>buf</c> is copied (<c>len</c> bytes) and placed
+ at the beginning of the queue.</p>
+ <p>The return value is 0.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>void</ret><nametext>add_driver_entry(ErlDrvEntry *de)</nametext></name>
- <fsummary>Add a driver entry</fsummary>
+ <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Push binary at the head of the driver queue</fsummary>
<desc>
- <marker id="add_driver_entry"></marker>
- <p>This function adds a driver entry to the list of drivers
- known by Erlang. The <seealso marker="driver_entry#init">init</seealso> function of the <c>de</c>
- parameter is called.</p>
- <note>
- <p>To use this function for adding drivers residing in
- dynamically loaded code is dangerous. If the driver code
- for the added driver resides in the same dynamically
- loaded module (i.e. <c>.so</c> file) as a normal
- dynamically loaded driver (loaded with the <c>erl_ddll</c>
- interface), the caller should call <seealso marker="#driver_lock_driver">driver_lock_driver</seealso> before
- adding driver entries.</p>
- <p>Use of this function is generally deprecated.</p>
- </note>
+ <marker id="driver_pushq_bin"></marker>
+ <p>This function puts data in the binary <c>bin</c>, at
+ <c>offset</c> with length <c>len</c> at the head of the
+ driver queue. It is most often faster than
+ <c>driver_pushq</c>, because the data doesn't have to be
+ copied.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
+ <p>The return value is 0.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>remove_driver_entry(ErlDrvEntry *de)</nametext></name>
- <fsummary>Remove a driver entry</fsummary>
+ <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name>
+ <fsummary>Push vector at the head of the driver queue</fsummary>
<desc>
- <marker id="remove_driver_entry"></marker>
- <p>This function removes a driver entry <c>de</c> previously
- added with <c>add_driver_entry</c>.</p>
- <p>Driver entries added by the <c>erl_ddll</c> erlang interface can
- not be removed by using this interface.</p>
+ <marker id="driver_pushqv"></marker>
+ <p>This function puts the data in <c>ev</c>, skipping the first
+ <c>skip</c> bytes of it, at the head of the driver queue.
+ It is faster than <c>driver_pushq</c>, because the data
+ doesn't have to be copied.</p>
+ <p>The return value is 0.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
</desc>
</func>
+
<func>
- <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name>
- <fsummary>Get erlang error atom name from error number</fsummary>
+ <name><ret>int</ret><nametext>driver_read_timer(ErlDrvPort port, unsigned long *time_left)</nametext></name>
+ <fsummary>Read the time left before timeout</fsummary>
<desc>
- <marker id="erl_errno_id"></marker>
- <p>This function returns the atom name of the erlang error,
- given the error number in <c>error</c>. Error atoms are:
- <c>einval</c>, <c>enoent</c>, etc. It can be used to make
- error terms from the driver.</p>
+ <marker id="driver_read_timer"></marker>
+ <p>This function reads the current time of a timer, and places
+ the result in <c>time_left</c>. This is the time in
+ milliseconds, before the timeout will occur.</p>
+ <p>The return value is 0.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void *</ret><nametext>driver_realloc(void *ptr, ErlDrvSizeT size)</nametext></name>
+ <fsummary>Resize an allocated memory block</fsummary>
+ <desc>
+ <marker id="driver_realloc"></marker>
+ <p>This function resizes a memory block, either in place, or by
+ allocating a new block, copying the data and freeing the old
+ block. A pointer is returned to the reallocated memory. On
+ failure (out of memory), <c>NULL</c> is returned. (This is
+ most often a wrapper for <c>realloc</c>.)</p>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvBinary *</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name>
+ <fsummary>Resize a driver binary</fsummary>
+ <desc>
+ <marker id="driver_realloc_binary"></marker>
+ <p>This function resizes a driver binary, while keeping the
+ data. The resized driver binary is returned. On failure (out
+ of memory), <c>NULL</c> is returned.</p>
+ <p>This function is only thread-safe when the emulator with SMP
+ support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on)</nametext></name>
+ <fsummary>Provide an event for having the emulator call the driver</fsummary>
+ <desc>
+ <marker id="driver_select"></marker>
+ <p>This function is used by drivers to provide the emulator with
+ events to check for. This enables the emulator to call the driver
+ when something has happened asynchronously.</p>
+ <p>The <c>event</c> argument identifies an OS-specific event object.
+ On Unix systems, the functions <c>select</c>/<c>poll</c> are used. The
+ event object must be a socket or pipe (or other object that
+ <c>select</c>/<c>poll</c> can use).
+ On windows, the Win32 API function <c>WaitForMultipleObjects</c>
+ is used. This places other restrictions on the event object.
+ Refer to the Win32 SDK documentation.</p>
+ <p>The <c>on</c> parameter should be <c>1</c> for setting events
+ and <c>0</c> for clearing them.</p>
+ <p>The <c>mode</c> argument is a bitwise-or combination of
+ <c>ERL_DRV_READ</c>, <c>ERL_DRV_WRITE</c> and <c>ERL_DRV_USE</c>.
+ The first two specify whether to wait for read events and/or write
+ events. A fired read event will call
+ <seealso marker="driver_entry#ready_input">ready_input</seealso>
+ while a fired write event will call
+ <seealso marker="driver_entry#ready_output">ready_output</seealso>.
+ </p>
+ <note>
+ <p>Some OS (Windows) do not differentiate between read and write events.
+ The call-back for a fired event then only depends on the value of <c>mode</c>.</p>
+ </note>
+ <p><c>ERL_DRV_USE</c> specifies if we are using the event object or if we want to close it.
+ On an emulator with SMP support, it is not safe to clear all events
+ and then close the event object after <c>driver_select</c> has
+ returned. Another thread may still be using the event object
+ internally. To safely close an event object call
+ <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>. That
+ will clear all events and then call
+ <seealso marker="driver_entry#stop_select">stop_select</seealso>
+ when it is safe to close the event object.
+ <c>ERL_DRV_USE</c> should be set together with the first event
+ for an event object. It is harmless to set <c>ERL_DRV_USE</c>
+ even though it already has been done. Clearing all events but keeping
+ <c>ERL_DRV_USE</c> set will indicate that we are using the event
+ object and probably will set events for it again.</p>
+ <note>
+ <p>ERL_DRV_USE was added in OTP release R13. Old drivers will still work
+ as before. But it is recommended to update them to use <c>ERL_DRV_USE</c> and
+ <c>stop_select</c> to make sure that event objects are closed in a safe way.</p>
+ </note>
+ <p>The return value is 0 (failure, -1, only if the
+ <c>ready_input</c>/<c>ready_output</c> is
+ <c>NULL</c>).</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name>
+ <fsummary>Send term data to other process than port owner process</fsummary>
+ <desc>
+ <marker id="driver_send_term"></marker>
+ <warning><p><c>driver_send_term()</c> is deprecated and will
+ be removed in the OTP-R17 release. Use
+ <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso>
+ instead.</p>
+ <p>Also note that parameters of <c>driver_send_term()</c>
+ cannot be properly checked by the runtime system when
+ executed by arbitrary threads. This may cause the
+ <c>driver_send_term()</c> function not to fail when
+ it should.</p>
+ </warning>
+ <p>The parameters <c>term</c> and <c>n</c> do the same thing
+ as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
+ <p>This function is only thread-safe when the emulator with SMP
+ support is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>driver_set_timer(ErlDrvPort port, unsigned long time)</nametext></name>
+ <fsummary>Set a timer to call the driver</fsummary>
+ <desc>
+ <marker id="driver_set_timer"></marker>
+ <p>This function sets a timer on the driver, which will count
+ down and call the driver when it is timed out. The
+ <c>time</c> parameter is the time in milliseconds before the
+ timer expires.</p>
+ <p>When the timer reaches 0 and expires, the driver entry
+ function <seealso marker="driver_entry#timeout">timeout</seealso> is called.</p>
+ <p>Note that there is only one timer on each driver instance;
+ setting a new timer will replace an older one.</p>
+ <p>Return value is 0 (-1 only when the <c>timeout</c> driver
+ function is <c>NULL</c>).</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name>
+ <fsummary>Return the size of the driver queue</fsummary>
+ <desc>
+ <marker id="driver_sizeq"></marker>
+ <p>This function returns the number of bytes currently in the
+ driver queue.</p>
+ <p>This function can be called from an arbitrary thread if a
+ <seealso marker="#ErlDrvPDL">port data lock</seealso>
+ associated with the <c>port</c> is locked by the calling
+ thread during the call.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>driver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size)</nametext></name>
+ <fsummary>Get information about the Erlang runtime system</fsummary>
+ <desc>
+ <marker id="driver_system_info"></marker>
+ <p>This function will write information about the Erlang runtime
+ system into the
+ <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
+ structure referred to by the first argument. The second
+ argument should be the size of the
+ <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
+ structure, i.e., <c>sizeof(ErlDrvSysInfo)</c>.</p>
+ <p>See the documentation of the
+ <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso>
+ structure for information about specific fields.</p>
</desc>
</func>
+<func>
+ <name><ret>ErlDrvSizeT</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len)</nametext></name>
+ <fsummary>Collect data segments into a buffer</fsummary>
+ <desc>
+ <marker id="driver_vec_to_buf"></marker>
+ <p>This function collects several segments of data, referenced
+ by <c>ev</c>, by copying them in order to the buffer
+ <c>buf</c>, of the size <c>len</c>.</p>
+ <p>If the data is to be sent from the driver to the port owner
+ process, it is faster to use <c>driver_outputv</c>.</p>
+ <p>The return value is the space left in the buffer, i.e. if
+ the <c>ev</c> contains less than <c>len</c> bytes it's the
+ difference, and if <c>ev</c> contains <c>len</c> bytes or
+ more, it's 0. This is faster if there is more than one header byte,
+ since the binary syntax can construct integers directly from
+ the binary.</p>
+ </desc>
+ </func>
+
<func>
<name><ret>void</ret><nametext>erl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high)</nametext></name>
<fsummary>Set and get limits for busy port message queue</fsummary>
@@ -1640,128 +1950,449 @@ typedef struct ErlIOVec {
function.</p>
</desc>
</func>
+
<func>
- <name><ret>void</ret><nametext>set_busy_port(ErlDrvPort port, int on)</nametext></name>
- <fsummary>Signal or unsignal port as busy</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_cond_broadcast(ErlDrvCond *cnd)</nametext></name>
+ <fsummary>Broadcast on a condition variable</fsummary>
<desc>
- <marker id="set_busy_port"></marker>
- <p>This function set and unset the busy state of the port. If
- <c>on</c> is non-zero, the port is set to busy, if it's zero the port
- is set to not busy. You typically want to combine
- this feature with the <seealso marker="#erl_drv_busy_msgq_limits">busy
- port message queue</seealso> functionality.</p>
- <p>Processes sending command data to the port will be suspended
- if either the port is busy or if the port message queue
- is busy. Suspended processes will be resumed when neither the
- port is busy, nor the port message queue is busy. Command data
- is in this context data passed to the port using either
- <c>Port ! {Owner, {command, Data}}</c>, or
- <c>port_command/[2,3]</c>.</p>
- <p>If the
- <seealso marker="driver_entry#driver_flags"><![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso>
- has been set in the
- <seealso marker="driver_entry">driver_entry</seealso>,
- data can be forced into the driver via
- <seealso marker="erlang#port_command/3">port_command(Port, Data, [force])</seealso>
- even though the driver has signaled that it is busy.
+ <marker id="erl_drv_cond_broadcast"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>cnd</c></tag>
+ <item>A pointer to a condition variable to broadcast on.</item>
+ </taglist>
+ <p>This function broadcasts on a condition variable. That is, if
+ other threads are waiting on the condition variable being
+ broadcast on, <em>all</em> of them will be woken.
</p>
- <p>For information about busy port message queue functionality
- see the documentation of the
- <seealso marker="#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso>
- function.</p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>void</ret><nametext>set_port_control_flags(ErlDrvPort port, int flags)</nametext></name>
- <fsummary>Set flags on how to handle control entry function</fsummary>
+ <name><ret>ErlDrvCond *</ret><nametext>erl_drv_cond_create(char *name)</nametext></name>
+ <fsummary>Create a condition variable</fsummary>
<desc>
- <marker id="set_port_control_flags"></marker>
- <p>This function sets flags for how the <seealso marker="driver_entry#control">control</seealso> driver entry
- function will return data to the port owner process. (The
- <c>control</c> function is called from <c>port_control/3</c>
- in erlang.)</p>
- <p>Currently there are only two meaningful values for
- <c>flags</c>: 0 means that data is returned in a list, and
- <c>PORT_CONTROL_FLAG_BINARY</c> means data is returned as
- a binary from <c>control</c>.</p>
+ <marker id="erl_drv_cond_create"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>A string identifying the created condition variable. It
+ will be used to identify the condition variable in planned
+ future debug functionality.
+ </item>
+ </taglist>
+ <p>This function creates a condition variable and returns a
+ pointer to it. On failure <c>NULL</c> is returned. The driver
+ creating the condition variable has the responsibility of
+ destroying it before the driver is unloaded.</p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_failure_eof(ErlDrvPort port)</nametext></name>
- <fsummary>Fail with EOF</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_cond_destroy(ErlDrvCond *cnd)</nametext></name>
+ <fsummary>Destroy a condition variable</fsummary>
<desc>
- <marker id="driver_failure_eof"></marker>
- <p>This function signals to erlang that the driver has
- encountered an EOF and should be closed, unless the port was
- opened with the <c>eof</c> option, in that case eof is sent
- to the port. Otherwise, the port is closed and an
- <c>'EXIT'</c> message is sent to the port owner process.</p>
- <p>The return value is 0.</p>
+ <marker id="erl_drv_cond_destroy"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>cnd</c></tag>
+ <item>A pointer to a condition variable to destroy.</item>
+ </taglist>
+ <p>This function destroys a condition variable previously
+ created by
+ <seealso marker="#erl_drv_cond_create">erl_drv_cond_create()</seealso>.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+ <func>
+ <name><ret>char *</ret><nametext>erl_drv_cond_name(ErlDrvCond *cnd)</nametext></name>
+ <fsummary>Get name of driver mutex.</fsummary>
+ <desc>
+ <marker id="erl_drv_cnd_name"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>cnd</c></tag>
+ <item>A pointer to an initialized condition.</item>
+ </taglist>
+ <p>
+ Returns a pointer to the name of the condition.
+ </p>
+ <note>
+ <p>This function is intended for debugging purposes only.</p>
+ </note>
+ </desc>
+ </func>
+
<func>
- <name><ret>int</ret><nametext>driver_failure_atom(ErlDrvPort port, char *string)</nametext></name>
- <name><ret>int</ret><nametext>driver_failure_posix(ErlDrvPort port, int error)</nametext></name>
- <name><ret>int</ret><nametext>driver_failure(ErlDrvPort port, int error)</nametext></name>
- <fsummary>Fail with error</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_cond_signal(ErlDrvCond *cnd)</nametext></name>
+ <fsummary>Signal on a condition variable</fsummary>
<desc>
- <marker id="driver_failure_atom"></marker>
- <marker id="driver_failure_posix"></marker>
- <marker id="driver_failure"></marker>
- <p>These functions signal to Erlang that the driver has
- encountered an error and should be closed. The port is
- closed and the tuple <c>{'EXIT', error, Err}</c>, is sent to
- the port owner process, where error is an error atom
- (<c>driver_failure_atom</c> and
- <c>driver_failure_posix</c>), or an integer
- (<c>driver_failure</c>).</p>
- <p>The driver should fail only when in severe error situations,
- when the driver cannot possibly keep open, for instance
- buffer allocation gets out of memory. For normal errors
- it is more appropriate to send error codes with
- <c>driver_output</c>.</p>
- <p>The return value is 0.</p>
+ <marker id="erl_drv_cond_signal"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>cnd</c></tag>
+ <item>A pointer to a condition variable to signal on.</item>
+ </taglist>
+ <p>This function signals on a condition variable. That is, if
+ other threads are waiting on the condition variable being
+ signaled, <em>one</em> of them will be woken.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvTermData</ret><nametext>driver_connected(ErlDrvPort port)</nametext></name>
- <fsummary>Return the port owner process</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Wait on a condition variable</fsummary>
<desc>
- <marker id="driver_connected"></marker>
- <p>This function returns the port owner process.</p>
- <p>Note that this function is <em>not</em> thread-safe, not
- even when the emulator with SMP support is used.</p>
+ <marker id="erl_drv_cond_wait"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>cnd</c></tag>
+ <item>A pointer to a condition variable to wait on.</item>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to a mutex to unlock while waiting.</item>
+ <tag><c></c></tag>
+ <item></item>
+ </taglist>
+ <p>This function waits on a condition variable. The calling
+ thread is blocked until another thread wakes it by signaling
+ or broadcasting on the condition variable. Before the calling
+ thread is blocked it unlocks the mutex passed as argument, and
+ when the calling thread is woken it locks the same mutex before
+ returning. That is, the mutex currently has to be locked by
+ the calling thread when calling this function.
+ </p>
+ <note><p><c>erl_drv_cond_wait()</c> might return even though
+ no-one has signaled or broadcast on the condition
+ variable. Code calling <c>erl_drv_cond_wait()</c> should
+ always be prepared for <c>erl_drv_cond_wait()</c>
+ returning even though the condition that the thread was
+ waiting for hasn't occurred. That is, when returning from
+ <c>erl_drv_cond_wait()</c> always check if the condition
+ has occurred, and if not call <c>erl_drv_cond_wait()</c>
+ again.
+ </p></note>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvTermData</ret><nametext>driver_caller(ErlDrvPort port)</nametext></name>
- <fsummary>Return the process making the driver call</fsummary>
+ <name><ret>int</ret><nametext>erl_drv_consume_timeslice(ErlDrvPort port, int percent)</nametext></name>
+ <fsummary>Give the runtime system a hint about how much CPU time the
+ current driver callback call has consumed</fsummary>
<desc>
- <marker id="driver_caller"></marker>
- <p>This function returns the process id of the process that
- made the current call to the driver. The process id can be
- used with <c>driver_send_term</c> to send back data to the
- caller. <c>driver_caller()</c> only returns valid data
- when currently executing in one of the following driver
- callbacks:</p>
- <taglist>
- <tag><seealso marker="driver_entry#start">start</seealso></tag>
- <item>Called from <c>open_port/2</c>.</item>
- <tag><seealso marker="driver_entry#output">output</seealso></tag>
- <item>Called from <c>erlang:send/2</c>, and
- <c>erlang:port_command/2</c></item>
- <tag><seealso marker="driver_entry#outputv">outputv</seealso></tag>
- <item>Called from <c>erlang:send/2</c>, and
- <c>erlang:port_command/2</c></item>
- <tag><seealso marker="driver_entry#control">control</seealso></tag>
- <item>Called from <c>erlang:port_control/3</c></item>
- <tag><seealso marker="driver_entry#call">call</seealso></tag>
- <item>Called from <c>erlang:port_call/3</c></item>
- </taglist>
- <p>Note that this function is <em>not</em> thread-safe, not
- even when the emulator with SMP support is used.</p>
+ <marker id="erl_drv_consume_timeslice"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>Port handle of the executing port.</item>
+ <tag><c>percent</c></tag>
+ <item>Approximate consumed fraction of a full
+ time-slice in percent.</item>
+ </taglist>
+ <p>Give the runtime system a hint about how much CPU time the
+ current driver callback call has consumed since last hint, or
+ since the start of the callback if no previous hint has been given.
+ The time is given as a fraction, in percent, of a full time-slice
+ that a port is allowed to execute before it should surrender the
+ CPU to other runnable ports or processes. Valid range is
+ <c>[1, 100]</c>. The scheduling time-slice is not an exact entity,
+ but can usually be approximated to about 1 millisecond.</p>
+
+ <p>Note that it is up to the runtime system to determine if and
+ how to use this information. Implementations on some platforms
+ may use other means in order to determine the consumed fraction
+ of the time-slice. Lengthy driver callbacks should regardless of
+ this frequently call the <c>erl_drv_consume_timeslice()</c>
+ function in order to determine if it is allowed to continue
+ execution or not.</p>
+
+ <p><c>erl_drv_consume_timeslice()</c> returns a non-zero value
+ if the time-slice has been exhausted, and zero if the callback is
+ allowed to continue execution. If a non-zero value is
+ returned the driver callback should return as soon as possible in
+ order for the port to be able to yield.</p>
+
+ <p>This function is provided to better support co-operative scheduling,
+ improve system responsiveness, and to make it easier to prevent
+ misbehaviors of the VM due to a port monopolizing a scheduler thread.
+ It can be used when dividing length work into a number of repeated
+ driver callback calls without the need to use threads. Also see the
+ important <seealso marker="#WARNING">warning</seealso> text at the
+ beginning of this document.</p>
</desc>
</func>
+
+ <func>
+ <name><ret>ErlDrvTime</ret><nametext>erl_drv_convert_time_unit(ErlDrvTime val, ErlDrvTimeUnit from, ErlDrvTimeUnit to)</nametext></name>
+ <fsummary>Convert time unit of a time value</fsummary>
+ <desc>
+ <marker id="erl_drv_convert_time_unit"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>val</c></tag>
+ <item>Value to convert time unit for.</item>
+ <tag><c>from</c></tag>
+ <item>Time unit of <c>val</c>.</item>
+ <tag><c>to</c></tag>
+ <item>Time unit of returned value.</item>
+ </taglist>
+ <p>Converts the <c>val</c> value of time unit <c>from</c> to
+ the corresponding value of time unit <c>to</c>. The result is
+ rounded using the floor function.</p>
+ <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
+ time unit argument.</p>
+ <p>See also:</p>
+ <list>
+ <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
+ <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>erl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2)</nametext></name>
+ <fsummary>Compare thread identifiers for equality</fsummary>
+ <desc>
+ <marker id="erl_drv_equal_tids"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>tid1</c></tag>
+ <item>A thread identifier.</item>
+ <tag><c>tid2</c></tag>
+ <item>A thread identifier.</item>
+ </taglist>
+ <p>This function compares two thread identifiers for equality,
+ and returns <c>0</c> it they aren't equal, and
+ a value not equal to <c>0</c> if they are equal.</p>
+ <note><p>A Thread identifier may be reused very quickly after
+ a thread has terminated. Therefore, if a thread
+ corresponding to one of the involved thread identifiers
+ has terminated since the thread identifier was saved,
+ the result of <c>erl_drv_equal_tids()</c> might not give
+ the expected result.
+ </p></note>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>erl_drv_getenv(const char *key, char *value, size_t *value_size)</nametext></name>
+ <fsummary>Get the value of an environment variable</fsummary>
+ <desc>
+ <marker id="erl_drv_getenv"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>key</c></tag>
+ <item>A null terminated string containing the
+ name of the environment variable.</item>
+ <tag><c>value</c></tag>
+ <item>A pointer to an output buffer.</item>
+ <tag><c>value_size</c></tag>
+ <item>A pointer to an integer. The integer is both used for
+ passing input and output sizes (see below).
+ </item>
+ </taglist>
+ <p>This function retrieves the value of an environment variable.
+ When called, <c>*value_size</c> should contain the size of
+ the <c>value</c> buffer. On success <c>0</c> is returned,
+ the value of the environment variable has been written to
+ the <c>value</c> buffer, and <c>*value_size</c> contains the
+ string length (excluding the terminating null character) of
+ the value written to the <c>value</c> buffer. On failure,
+ i.e., no such environment variable was found, a value less than
+ <c>0</c> is returned. When the size of the <c>value</c>
+ buffer is too small, a value greater than <c>0</c> is returned
+ and <c>*value_size</c> has been set to the buffer size needed.
+ </p>
+ <warning><p>Do <em>not</em> use libc's <c>getenv</c> or similar
+ C library interfaces from a driver.
+ </p></warning>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>erl_drv_init_ack(ErlDrvPort port, ErlDrvData res)</nametext></name>
+ <fsummary>Acknowledge the start of the port</fsummary>
+ <desc>
+ <marker id="erl_drv_init_ack"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>The port handle of the port (driver instance) creating
+ doing the acknowledgment.
+ </item>
+ <tag><c>res</c></tag>
+ <item>The result of the port initialization. This can be the same values
+ as the return value of <seealso marker="driver_entry#start">start</seealso>,
+ i.e any of the error codes or the ErlDrvData that is to be used for this
+ port.
+ </item>
+ </taglist>
+ <p>
+ When this function is called the initiating erlang:open_port call is
+ returned as if the <seealso marker="driver_entry#start">start</seealso>
+ function had just been called. It can only be used when the
+ <seealso marker="driver_entry#driver_flags">ERL_DRV_FLAG_USE_INIT_ACK</seealso>
+ flag has been set on the linked-in driver.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvTime</ret><nametext>erl_drv_monotonic_time(ErlDrvTimeUnit time_unit)</nametext></name>
+ <fsummary>Get Erlang Monotonic Time</fsummary>
+ <desc>
+ <marker id="erl_drv_monotonic_time"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>time_unit</c></tag>
+ <item>Time unit of returned value.</item>
+ </taglist>
+ <p>
+ Returns
+ <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang
+ monotonic time</seealso>. Note that it is not uncommon with
+ negative values.
+ </p>
+ <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
+ time unit argument, or if called from a thread that is not a
+ scheduler thread.</p>
+ <p>See also:</p>
+ <list>
+ <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
+ <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>ErlDrvMutex *</ret><nametext>erl_drv_mutex_create(char *name)</nametext></name>
+ <fsummary>Create a mutex</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_create"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>A string identifying the created mutex. It will be used
+ to identify the mutex in planned future debug functionality.
+ </item>
+ </taglist>
+ <p>This function creates a mutex and returns a pointer to it. On
+ failure <c>NULL</c> is returned. The driver creating the mutex
+ has the responsibility of destroying it before the driver is
+ unloaded.
+ </p>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>erl_drv_mutex_destroy(ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Destroy a mutex</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_destroy"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to a mutex to destroy.</item>
+ </taglist>
+ <p>This function destroys a mutex previously created by
+ <seealso marker="#erl_drv_mutex_create">erl_drv_mutex_create()</seealso>.
+ The mutex has to be in an unlocked state before being
+ destroyed.
+ </p>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>erl_drv_mutex_lock(ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Lock a mutex</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_lock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to a mutex to lock.</item>
+ </taglist>
+ <p>This function locks a mutex. The calling thread will be
+ blocked until the mutex has been locked. A thread
+ which currently has locked the mutex may <em>not</em> lock
+ the same mutex again.
+ </p>
+ <warning><p>If you leave a mutex locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>char *</ret><nametext>erl_drv_mutex_name(ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Get name of driver mutex.</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_name"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to an initialized mutex.</item>
+ </taglist>
+ <p>
+ Returns a pointer to the name of the mutex.
+ </p>
+ <note>
+ <p>This function is intended for debugging purposes only.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>erl_drv_mutex_trylock(ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Try lock a mutex</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_trylock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to a mutex to try to lock.</item>
+ </taglist>
+ <p>This function tries to lock a mutex. If successful <c>0</c>,
+ is returned; otherwise, <c>EBUSY</c> is returned. A thread
+ which currently has locked the mutex may <em>not</em> try to
+ lock the same mutex again.
+ </p>
+ <warning><p>If you leave a mutex locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>void</ret><nametext>erl_drv_mutex_unlock(ErlDrvMutex *mtx)</nametext></name>
+ <fsummary>Unlock a mutex</fsummary>
+ <desc>
+ <marker id="erl_drv_mutex_unlock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>mtx</c></tag>
+ <item>A pointer to a mutex to unlock.</item>
+ </taglist>
+ <p>This function unlocks a mutex. The mutex currently has to be
+ locked by the calling thread.
+ </p>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
<func>
<name><ret>int</ret><nametext>erl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n)</nametext></name>
<fsummary>Send term data from driver to port owner</fsummary>
@@ -1939,255 +2570,237 @@ ERL_DRV_MAP int sz
support is used.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n)</nametext></name>
- <fsummary>Send term data from driver to port owner</fsummary>
+ <name><ret>int</ret><nametext>erl_drv_putenv(const char *key, char *value)</nametext></name>
+ <fsummary>Set the value of an environment variable</fsummary>
<desc>
- <marker id="driver_output_term"></marker>
- <warning><p><c>driver_output_term()</c> is deprecated and will
- be removed in the OTP-R17 release. Use
- <seealso marker="#erl_drv_send_term">erl_drv_output_term()</seealso>
- instead.</p>
- </warning>
- <p>The parameters <c>term</c> and <c>n</c> do the same thing
- as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
- <p>Note that this function is <em>not</em> thread-safe, not
- even when the emulator with SMP support is used.</p>
+ <marker id="erl_drv_putenv"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>key</c></tag>
+ <item>A null terminated string containing the
+ name of the environment variable.</item>
+ <tag><c>value</c></tag>
+ <item>A null terminated string containing the
+ new value of the environment variable.</item>
+ </taglist>
+ <p>This function sets the value of an environment variable.
+ It returns <c>0</c> on success, and a value <c>!= 0</c> on
+ failure.
+ </p>
+ <note><p>The result of passing the empty string ("") as a value
+ is platform dependent. On some platforms the value of the
+ variable is set to the empty string, on others, the
+ environment variable is removed.</p>
+ </note>
+ <warning><p>Do <em>not</em> use libc's <c>putenv</c> or similar
+ C library interfaces from a driver.
+ </p></warning>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvTermData</ret><nametext>driver_mk_atom(char* string)</nametext></name>
- <fsummary>Make an atom from a name</fsummary>
+ <name><ret>ErlDrvRWLock *</ret><nametext>erl_drv_rwlock_create(char *name)</nametext></name>
+ <fsummary>Create an rwlock</fsummary>
<desc>
- <marker id="driver_mk_atom"></marker>
- <p>This function returns an atom given a name
- <c>string</c>. The atom is created and won't change, so the
- return value may be saved and reused, which is faster than
- looking up the atom several times.</p>
- <p>Note that this function is <em>not</em> thread-safe, not
- even when the emulator with SMP support is used.</p>
+ <marker id="erl_drv_rwlock_create"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>A string identifying the created rwlock. It will be used to
+ identify the rwlock in planned future debug functionality.
+ </item>
+ </taglist>
+ <p>This function creates an rwlock and returns a pointer to it. On
+ failure <c>NULL</c> is returned. The driver creating the rwlock
+ has the responsibility of destroying it before the driver is
+ unloaded.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvTermData</ret><nametext>driver_mk_port(ErlDrvPort port)</nametext></name>
- <fsummary>Make a erlang term port from a port</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_rwlock_destroy(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Destroy an rwlock</fsummary>
<desc>
- <marker id="driver_mk_port"></marker>
- <p>This function converts a port handle to the erlang term
- format, usable in the <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>, and <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> functions.</p>
- <p>Note that this function is <em>not</em> thread-safe, not
- even when the emulator with SMP support is used.</p>
+ <marker id="erl_drv_rwlock_destroy"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to destroy.</item>
+ </taglist>
+ <p>This function destroys an rwlock previously created by
+ <seealso marker="#erl_drv_rwlock_create">erl_drv_rwlock_create()</seealso>.
+ The rwlock has to be in an unlocked state before being destroyed.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
+ <func>
+ <name><ret>char *</ret><nametext>erl_drv_rwlock_name(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Get name of driver mutex.</fsummary>
+ <desc>
+ <marker id="erl_drv_rwlock_name"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an initialized r/w-lock.</item>
+ </taglist>
+ <p>
+ Returns a pointer to the name of the r/w-lock.
+ </p>
+ <note>
+ <p>This function is intended for debugging purposes only.</p>
+ </note>
+ </desc>
+ </func>
+
<func>
- <name><ret>int</ret><nametext>erl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name>
- <fsummary>Send term data to other process than port owner process</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_rwlock_rlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Read lock an rwlock</fsummary>
<desc>
- <marker id="erl_drv_send_term"></marker>
- <p>This function is the only way for a driver to send data to
- <em>other</em> processes than the port owner process. The
- <c>receiver</c> parameter specifies the process to receive
- the data.</p>
- <note><p>Note that the <c>port</c> parameter is <em>not</em>
- an ordinary port handle, but a port handle converted using
- <c>driver_mk_port()</c>.</p></note>
- <p>The parameters <c>port</c>, <c>term</c> and <c>n</c> do the same thing
- as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
- <p>This function is only thread-safe when the emulator with SMP
- support is used.</p>
+ <marker id="erl_drv_rwlock_rlock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to read lock.</item>
+ </taglist>
+ <p>This function read locks an rwlock. The calling thread will be
+ blocked until the rwlock has been read locked. A thread
+ which currently has read or read/write locked the rwlock may
+ <em>not</em> lock the same rwlock again.
+ </p>
+ <warning><p>If you leave an rwlock locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name>
- <fsummary>Send term data to other process than port owner process</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Read unlock an rwlock</fsummary>
<desc>
- <marker id="driver_send_term"></marker>
- <warning><p><c>driver_send_term()</c> is deprecated and will
- be removed in the OTP-R17 release. Use
- <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso>
- instead.</p>
- <p>Also note that parameters of <c>driver_send_term()</c>
- cannot be properly checked by the runtime system when
- executed by arbitrary threads. This may cause the
- <c>driver_send_term()</c> function not to fail when
- it should.</p>
- </warning>
- <p>The parameters <c>term</c> and <c>n</c> do the same thing
- as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
- <p>This function is only thread-safe when the emulator with SMP
- support is used.</p>
+ <marker id="erl_drv_rwlock_runlock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to read unlock.</item>
+ </taglist>
+ <p>This function read unlocks an rwlock. The rwlock currently
+ has to be read locked by the calling thread.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
- <func>
- <name><ret>long</ret><nametext>driver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*))</nametext></name>
- <fsummary>Perform an asynchronous call within a driver</fsummary>
- <desc>
- <marker id="driver_async"></marker>
- <p>This function performs an asynchronous call. The function
- <c>async_invoke</c> is invoked in a thread separate from the
- emulator thread. This enables the driver to perform
- time-consuming, blocking operations without blocking the
- emulator.</p>
- <p>The async thread pool size can be set with the
- <seealso marker="erl#async_thread_pool_size">+A</seealso>
- command line argument of <seealso marker="erl">erl(1)</seealso>.
- If no async thread pool is available, the call is made
- synchronously in the thread calling <c>driver_async()</c>. The
- current number of async threads in the async thread pool can be
- retrieved via
- <seealso marker="#driver_system_info">driver_system_info()</seealso>.</p>
- <p>If there is a thread pool available, a thread will be
- used. If the <c>key</c> argument is null, the threads from the
- pool are used in a round-robin way, each call to
- <c>driver_async</c> uses the next thread in the pool. With the
- <c>key</c> argument set, this behaviour is changed. The two
- same values of <c>*key</c> always get the same thread.</p>
- <p>To make sure that a driver instance always uses the same
- thread, the following call can be used:</p>
- <p></p>
- <code type="none"><![CDATA[
- unsigned int myKey = driver_async_port_key(myPort);
- r = driver_async(myPort, &myKey, myData, myFunc);
- ]]></code>
- <p>It is enough to initialize <c>myKey</c> once for each
- driver instance.</p>
- <p>If a thread is already working, the calls will be
- queued up and executed in order. Using the same thread for
- each driver instance ensures that the calls will be made in
- sequence.</p>
- <p>The <c>async_data</c> is the argument to the functions
- <c>async_invoke</c> and <c>async_free</c>. It's typically a
- pointer to a structure that contains a pipe or event that
- can be used to signal that the async operation completed.
- The data should be freed in <c>async_free</c>.</p>
- <p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver
- entry function is called. If <c>ready_async</c> is null in
- the driver entry, the <c>async_free</c> function is called
- instead.</p>
- <p>The return value is -1 if the <c>driver_async</c> call
- fails.</p>
- <note>
- <p>As of erts version 5.5.4.3 the default stack size for
- threads in the async-thread pool is 16 kilowords,
- i.e., 64 kilobyte on 32-bit architectures.
- This small default size has been chosen since the
- amount of async-threads might be quite large. The
- default stack size is enough for drivers delivered
- with Erlang/OTP, but might not be sufficiently large
- for other dynamically linked in drivers that use the
- driver_async() functionality. A suggested stack size
- for threads in the async-thread pool can be configured
- via the
- <seealso marker="erl#async_thread_stack_size">+a</seealso>
- command line argument of
- <seealso marker="erl">erl(1)</seealso>.</p>
- </note>
- </desc>
- </func>
<func>
- <name><ret>unsigned int</ret><nametext>driver_async_port_key (ErlDrvPort port)</nametext></name>
- <fsummary>Calculate an async key from an ErlDrvPort</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_rwlock_rwlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Read/Write lock an rwlock</fsummary>
<desc>
- <marker id="driver_async_port_key"></marker>
- <p>This function calculates a key for later use in <seealso
- marker="#driver_async">driver_async()</seealso>. The keys are
- evenly distributed so that a fair mapping between port id's
- and async thread id's is achieved.</p>
- <note>
- <p>Before OTP-R16, the actual port id could be used as a key
- with proper casting, but after the rewrite of the port
- subsystem, this is no longer the case. With this function, you
- can achieve the same distribution based on port id's as before
- OTP-R16.</p>
- </note>
+ <marker id="erl_drv_rwlock_rwlock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to read/write lock.</item>
+ </taglist>
+ <p>This function read/write locks an rwlock. The calling thread
+ will be blocked until the rwlock has been read/write locked.
+ A thread which currently has read or read/write locked the
+ rwlock may <em>not</em> lock the same rwlock again.
+ </p>
+ <warning><p>If you leave an rwlock locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>driver_lock_driver(ErlDrvPort port)</nametext></name>
- <fsummary>Make sure the driver is never unloaded</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Read/Write unlock an rwlock</fsummary>
<desc>
- <marker id="driver_lock_driver"></marker>
- <p>This function locks the driver used by the port <c>port</c>
- in memory for the rest of the emulator process'
- lifetime. After this call, the driver behaves as one of Erlang's
- statically linked in drivers.</p>
+ <marker id="erl_drv_rwlock_rwunlock"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to read/write unlock.</item>
+ </taglist>
+ <p>This function read/write unlocks an rwlock. The rwlock
+ currently has to be read/write locked by the calling thread.
+ </p>
+ <p>This function is thread-safe.</p>
</desc>
</func>
+
<func>
- <name><ret>ErlDrvPort</ret><nametext>driver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data)</nametext></name>
- <fsummary>Create a new port (driver instance)</fsummary>
+ <name><ret>int</ret><nametext>erl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Try to read lock an rwlock</fsummary>
<desc>
- <p>This function creates a new port executing the same driver
- code as the port creating the new port.
- A short description of the arguments:</p>
+ <marker id="erl_drv_rwlock_tryrlock"></marker>
+ <p>Arguments:</p>
<taglist>
- <tag><c>port</c></tag>
- <item>The port handle of the port (driver instance) creating
- the new port.</item>
- <tag><c>owner_pid</c></tag>
- <item>The process id of the Erlang process which will be
- owner of the new port. This process will be linked
- to the new port. You usually want to use
- <c>driver_caller(port)</c> as <c>owner_pid</c>.</item>
- <tag><c>name</c></tag>
- <item>The port name of the new port. You usually want to
- use the same port name as the driver name
- (<seealso marker="driver_entry#driver_name">driver_name</seealso>
- field of the
- <seealso marker="driver_entry">driver_entry</seealso>).</item>
- <tag><c>drv_data</c></tag>
- <item>The driver defined handle that will be passed in subsequent
- calls to driver call-backs. Note, that the
- <seealso marker="driver_entry#start">driver start call-back</seealso>
- will not be called for this new driver instance.
- The driver defined handle is normally created in the
- <seealso marker="driver_entry#start">driver start call-back</seealso>
- when a port is created via
- <seealso marker="erlang#open_port/2">erlang:open_port/2</seealso>. </item>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to try to read lock.</item>
</taglist>
- <p>The caller of <c>driver_create_port()</c> is allowed to
- manipulate the newly created port when <c>driver_create_port()</c>
- has returned. When
- <seealso marker="#smp_support">port level locking</seealso>
- is used, the creating port is, however, only allowed to
- manipulate the newly created port until the current driver
- call-back that was called by the emulator returns.</p>
- <note>
- <p>When
- <seealso marker="#smp_support">port level locking</seealso>
- is used, the creating port is only allowed to manipulate
- the newly created port until the current driver call-back
- returns.</p>
- </note>
+ <p>This function tries to read lock an rwlock. If successful
+ <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned.
+ A thread which currently has read or read/write locked the
+ rwlock may <em>not</em> try to lock the same rwlock again.
+ </p>
+ <warning><p>If you leave an rwlock locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
</desc>
</func>
<func>
- <name><ret>void</ret><nametext>erl_drv_init_ack(ErlDrvPort port, ErlDrvData res)</nametext></name>
- <fsummary>Acknowledge the start of the port</fsummary>
+ <name><ret>int</ret><nametext>erl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck)</nametext></name>
+ <fsummary>Try to read/write lock an rwlock</fsummary>
<desc>
- <marker id="erl_drv_init_ack"></marker>
+ <marker id="erl_drv_rwlock_tryrwlock"></marker>
<p>Arguments:</p>
<taglist>
- <tag><c>port</c></tag>
- <item>The port handle of the port (driver instance) creating
- doing the acknowledgment.
- </item>
- <tag><c>res</c></tag>
- <item>The result of the port initialization. This can be the same values
- as the return value of <seealso marker="driver_entry#start">start</seealso>,
- i.e any of the error codes or the ErlDrvData that is to be used for this
- port.
- </item>
+ <tag><c>rwlck</c></tag>
+ <item>A pointer to an rwlock to try to read/write lock.</item>
</taglist>
- <p>
- When this function is called the initiating erlang:open_port call is
- returned as if the <seealso marker="driver_entry#start">start</seealso>
- function had just been called. It can only be used when the
- <seealso marker="driver_entry#driver_flags">ERL_DRV_FLAG_USE_INIT_ACK</seealso>
- flag has been set on the linked-in driver.
- </p>
+ <p>This function tries to read/write lock an rwlock. If successful
+ <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned.
+ A thread which currently has read or read/write locked the
+ rwlock may <em>not</em> try to lock the same rwlock again.
+ </p>
+ <warning><p>If you leave an rwlock locked in an emulator thread
+ when you let the thread out of your control, you will
+ <em>very likely</em> deadlock the whole emulator.
+ </p></warning>
+ <p>This function is thread-safe.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>erl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name>
+ <fsummary>Send term data to other process than port owner process</fsummary>
+ <desc>
+ <marker id="erl_drv_send_term"></marker>
+ <p>This function is the only way for a driver to send data to
+ <em>other</em> processes than the port owner process. The
+ <c>receiver</c> parameter specifies the process to receive
+ the data.</p>
+ <note><p>Note that the <c>port</c> parameter is <em>not</em>
+ an ordinary port handle, but a port handle converted using
+ <c>driver_mk_port()</c>.</p></note>
+ <p>The parameters <c>port</c>, <c>term</c> and <c>n</c> do the same thing
+ as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p>
+ <p>This function is only thread-safe when the emulator with SMP
+ support is used.</p>
</desc>
</func>
@@ -2275,53 +2888,6 @@ ERL_DRV_MAP int sz
</func>
<func>
- <name><ret>ErlDrvThreadOpts *</ret><nametext>erl_drv_thread_opts_create(char *name)</nametext></name>
- <fsummary>Create thread options</fsummary>
- <desc>
- <marker id="erl_drv_thread_opts_create"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>name</c></tag>
- <item>A string identifying the created thread options. It will be used
- to identify the thread options in planned future debug
- functionality.
- </item>
- </taglist>
- <p>This function allocates and initialize a thread option
- structure. On failure <c>NULL</c> is returned. A thread option
- structure is used for passing options to
- <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>.
- If the structure isn't modified before it is passed to
- <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>,
- the default values will be used.
- </p>
- <warning><p>You are not allowed to allocate the
- <seealso marker="#ErlDrvThreadOpts">ErlDrvThreadOpts</seealso>
- structure by yourself. It has to be allocated and
- initialized by <c>erl_drv_thread_opts_create()</c>.
- </p></warning>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts)</nametext></name>
- <fsummary>Destroy thread options</fsummary>
- <desc>
- <marker id="erl_drv_thread_opts_destroy"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>opts</c></tag>
- <item>A pointer to thread options to destroy.</item>
- </taglist>
- <p>This function destroys thread options previously created by
- <seealso marker="#erl_drv_thread_opts_create">erl_drv_thread_opts_create()</seealso>.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
<name><ret>void</ret><nametext>erl_drv_thread_exit(void *exit_value)</nametext></name>
<fsummary>Terminate calling thread</fsummary>
<desc>
@@ -2368,418 +2934,124 @@ ERL_DRV_MAP int sz
</desc>
</func>
- <func>
- <name><ret>ErlDrvTid</ret><nametext>erl_drv_thread_self(void)</nametext></name>
- <fsummary>Get the thread identifier of the current thread</fsummary>
- <desc>
- <marker id="erl_drv_thread_self"></marker>
- <p>This function returns the thread identifier of the
- calling thread.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>int</ret><nametext>erl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2)</nametext></name>
- <fsummary>Compare thread identifiers for equality</fsummary>
- <desc>
- <marker id="erl_drv_equal_tids"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>tid1</c></tag>
- <item>A thread identifier.</item>
- <tag><c>tid2</c></tag>
- <item>A thread identifier.</item>
- </taglist>
- <p>This function compares two thread identifiers for equality,
- and returns <c>0</c> it they aren't equal, and
- a value not equal to <c>0</c> if they are equal.</p>
- <note><p>A Thread identifier may be reused very quickly after
- a thread has terminated. Therefore, if a thread
- corresponding to one of the involved thread identifiers
- has terminated since the thread identifier was saved,
- the result of <c>erl_drv_equal_tids()</c> might not give
- the expected result.
- </p></note>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>ErlDrvMutex *</ret><nametext>erl_drv_mutex_create(char *name)</nametext></name>
- <fsummary>Create a mutex</fsummary>
- <desc>
- <marker id="erl_drv_mutex_create"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>name</c></tag>
- <item>A string identifying the created mutex. It will be used
- to identify the mutex in planned future debug functionality.
- </item>
- </taglist>
- <p>This function creates a mutex and returns a pointer to it. On
- failure <c>NULL</c> is returned. The driver creating the mutex
- has the responsibility of destroying it before the driver is
- unloaded.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_mutex_destroy(ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Destroy a mutex</fsummary>
- <desc>
- <marker id="erl_drv_mutex_destroy"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>mtx</c></tag>
- <item>A pointer to a mutex to destroy.</item>
- </taglist>
- <p>This function destroys a mutex previously created by
- <seealso marker="#erl_drv_mutex_create">erl_drv_mutex_create()</seealso>.
- The mutex has to be in an unlocked state before being
- destroyed.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_mutex_lock(ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Lock a mutex</fsummary>
- <desc>
- <marker id="erl_drv_mutex_lock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>mtx</c></tag>
- <item>A pointer to a mutex to lock.</item>
- </taglist>
- <p>This function locks a mutex. The calling thread will be
- blocked until the mutex has been locked. A thread
- which currently has locked the mutex may <em>not</em> lock
- the same mutex again.
- </p>
- <warning><p>If you leave a mutex locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
- </p></warning>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>int</ret><nametext>erl_drv_mutex_trylock(ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Try lock a mutex</fsummary>
- <desc>
- <marker id="erl_drv_mutex_trylock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>mtx</c></tag>
- <item>A pointer to a mutex to try to lock.</item>
- </taglist>
- <p>This function tries to lock a mutex. If successful <c>0</c>,
- is returned; otherwise, <c>EBUSY</c> is returned. A thread
- which currently has locked the mutex may <em>not</em> try to
- lock the same mutex again.
- </p>
- <warning><p>If you leave a mutex locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
- </p></warning>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_mutex_unlock(ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Unlock a mutex</fsummary>
- <desc>
- <marker id="erl_drv_mutex_unlock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>mtx</c></tag>
- <item>A pointer to a mutex to unlock.</item>
- </taglist>
- <p>This function unlocks a mutex. The mutex currently has to be
- locked by the calling thread.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>ErlDrvCond *</ret><nametext>erl_drv_cond_create(char *name)</nametext></name>
- <fsummary>Create a condition variable</fsummary>
- <desc>
- <marker id="erl_drv_cond_create"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>name</c></tag>
- <item>A string identifying the created condition variable. It
- will be used to identify the condition variable in planned
- future debug functionality.
- </item>
- </taglist>
- <p>This function creates a condition variable and returns a
- pointer to it. On failure <c>NULL</c> is returned. The driver
- creating the condition variable has the responsibility of
- destroying it before the driver is unloaded.</p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_cond_destroy(ErlDrvCond *cnd)</nametext></name>
- <fsummary>Destroy a condition variable</fsummary>
- <desc>
- <marker id="erl_drv_cond_destroy"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>cnd</c></tag>
- <item>A pointer to a condition variable to destroy.</item>
- </taglist>
- <p>This function destroys a condition variable previously
- created by
- <seealso marker="#erl_drv_cond_create">erl_drv_cond_create()</seealso>.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_cond_signal(ErlDrvCond *cnd)</nametext></name>
- <fsummary>Signal on a condition variable</fsummary>
- <desc>
- <marker id="erl_drv_cond_signal"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>cnd</c></tag>
- <item>A pointer to a condition variable to signal on.</item>
- </taglist>
- <p>This function signals on a condition variable. That is, if
- other threads are waiting on the condition variable being
- signaled, <em>one</em> of them will be woken.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_cond_broadcast(ErlDrvCond *cnd)</nametext></name>
- <fsummary>Broadcast on a condition variable</fsummary>
- <desc>
- <marker id="erl_drv_cond_broadcast"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>cnd</c></tag>
- <item>A pointer to a condition variable to broadcast on.</item>
- </taglist>
- <p>This function broadcasts on a condition variable. That is, if
- other threads are waiting on the condition variable being
- broadcast on, <em>all</em> of them will be woken.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Wait on a condition variable</fsummary>
- <desc>
- <marker id="erl_drv_cond_wait"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>cnd</c></tag>
- <item>A pointer to a condition variable to wait on.</item>
- <tag><c>mtx</c></tag>
- <item>A pointer to a mutex to unlock while waiting.</item>
- <tag><c></c></tag>
- <item></item>
- </taglist>
- <p>This function waits on a condition variable. The calling
- thread is blocked until another thread wakes it by signaling
- or broadcasting on the condition variable. Before the calling
- thread is blocked it unlocks the mutex passed as argument, and
- when the calling thread is woken it locks the same mutex before
- returning. That is, the mutex currently has to be locked by
- the calling thread when calling this function.
- </p>
- <note><p><c>erl_drv_cond_wait()</c> might return even though
- no-one has signaled or broadcast on the condition
- variable. Code calling <c>erl_drv_cond_wait()</c> should
- always be prepared for <c>erl_drv_cond_wait()</c>
- returning even though the condition that the thread was
- waiting for hasn't occurred. That is, when returning from
- <c>erl_drv_cond_wait()</c> always check if the condition
- has occurred, and if not call <c>erl_drv_cond_wait()</c>
- again.
- </p></note>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
+ <func>
+ <name><ret>char *</ret><nametext>erl_drv_thread_name(ErlDrvTid tid)</nametext></name>
+ <fsummary>Get name of driver mutex.</fsummary>
+ <desc>
+ <marker id="erl_drv_rwlock_name"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>tid</c></tag>
+ <item>A thread identifier.</item>
+ </taglist>
+ <p>
+ Returns a pointer to the name of the thread.
+ </p>
+ <note>
+ <p>This function is intended for debugging purposes only.</p>
+ </note>
+ </desc>
+ </func>
<func>
- <name><ret>ErlDrvRWLock *</ret><nametext>erl_drv_rwlock_create(char *name)</nametext></name>
- <fsummary>Create an rwlock</fsummary>
+ <name><ret>ErlDrvThreadOpts *</ret><nametext>erl_drv_thread_opts_create(char *name)</nametext></name>
+ <fsummary>Create thread options</fsummary>
<desc>
- <marker id="erl_drv_rwlock_create"></marker>
+ <marker id="erl_drv_thread_opts_create"></marker>
<p>Arguments:</p>
<taglist>
<tag><c>name</c></tag>
- <item>A string identifying the created rwlock. It will be used to
- identify the rwlock in planned future debug functionality.
+ <item>A string identifying the created thread options. It will be used
+ to identify the thread options in planned future debug
+ functionality.
</item>
</taglist>
- <p>This function creates an rwlock and returns a pointer to it. On
- failure <c>NULL</c> is returned. The driver creating the rwlock
- has the responsibility of destroying it before the driver is
- unloaded.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_rwlock_destroy(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Destroy an rwlock</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_destroy"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to destroy.</item>
- </taglist>
- <p>This function destroys an rwlock previously created by
- <seealso marker="#erl_drv_rwlock_create">erl_drv_rwlock_create()</seealso>.
- The rwlock has to be in an unlocked state before being destroyed.
- </p>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>void</ret><nametext>erl_drv_rwlock_rlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Read lock an rwlock</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_rlock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to read lock.</item>
- </taglist>
- <p>This function read locks an rwlock. The calling thread will be
- blocked until the rwlock has been read locked. A thread
- which currently has read or read/write locked the rwlock may
- <em>not</em> lock the same rwlock again.
- </p>
- <warning><p>If you leave an rwlock locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
- </p></warning>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
-
- <func>
- <name><ret>int</ret><nametext>erl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Try to read lock an rwlock</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_tryrlock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to try to read lock.</item>
- </taglist>
- <p>This function tries to read lock an rwlock. If successful
- <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned.
- A thread which currently has read or read/write locked the
- rwlock may <em>not</em> try to lock the same rwlock again.
+ <p>This function allocates and initialize a thread option
+ structure. On failure <c>NULL</c> is returned. A thread option
+ structure is used for passing options to
+ <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>.
+ If the structure isn't modified before it is passed to
+ <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>,
+ the default values will be used.
</p>
- <warning><p>If you leave an rwlock locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
+ <warning><p>You are not allowed to allocate the
+ <seealso marker="#ErlDrvThreadOpts">ErlDrvThreadOpts</seealso>
+ structure by yourself. It has to be allocated and
+ initialized by <c>erl_drv_thread_opts_create()</c>.
</p></warning>
<p>This function is thread-safe.</p>
</desc>
</func>
<func>
- <name><ret>void</ret><nametext>erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Read unlock an rwlock</fsummary>
+ <name><ret>void</ret><nametext>erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts)</nametext></name>
+ <fsummary>Destroy thread options</fsummary>
<desc>
- <marker id="erl_drv_rwlock_runlock"></marker>
+ <marker id="erl_drv_thread_opts_destroy"></marker>
<p>Arguments:</p>
<taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to read unlock.</item>
+ <tag><c>opts</c></tag>
+ <item>A pointer to thread options to destroy.</item>
</taglist>
- <p>This function read unlocks an rwlock. The rwlock currently
- has to be read locked by the calling thread.
+ <p>This function destroys thread options previously created by
+ <seealso marker="#erl_drv_thread_opts_create">erl_drv_thread_opts_create()</seealso>.
</p>
<p>This function is thread-safe.</p>
</desc>
</func>
<func>
- <name><ret>void</ret><nametext>erl_drv_rwlock_rwlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Read/Write lock an rwlock</fsummary>
+ <name><ret>ErlDrvTid</ret><nametext>erl_drv_thread_self(void)</nametext></name>
+ <fsummary>Get the thread identifier of the current thread</fsummary>
<desc>
- <marker id="erl_drv_rwlock_rwlock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to read/write lock.</item>
- </taglist>
- <p>This function read/write locks an rwlock. The calling thread
- will be blocked until the rwlock has been read/write locked.
- A thread which currently has read or read/write locked the
- rwlock may <em>not</em> lock the same rwlock again.
+ <marker id="erl_drv_thread_self"></marker>
+ <p>This function returns the thread identifier of the
+ calling thread.
</p>
- <warning><p>If you leave an rwlock locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
- </p></warning>
<p>This function is thread-safe.</p>
</desc>
</func>
- <func>
- <name><ret>int</ret><nametext>erl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Try to read/write lock an rwlock</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_tryrwlock"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to try to read/write lock.</item>
- </taglist>
- <p>This function tries to read/write lock an rwlock. If successful
- <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned.
- A thread which currently has read or read/write locked the
- rwlock may <em>not</em> try to lock the same rwlock again.
- </p>
- <warning><p>If you leave an rwlock locked in an emulator thread
- when you let the thread out of your control, you will
- <em>very likely</em> deadlock the whole emulator.
- </p></warning>
- <p>This function is thread-safe.</p>
- </desc>
- </func>
+ <func>
+ <name><ret>ErlDrvTime</ret><nametext>erl_drv_time_offset(ErlDrvTimeUnit time_unit)</nametext></name>
+ <fsummary>Get current Time Offset</fsummary>
+ <desc>
+ <marker id="erl_drv_time_offset"></marker>
+ <p>Arguments:</p>
+ <taglist>
+ <tag><c>time_unit</c></tag>
+ <item>Time unit of returned value.</item>
+ </taglist>
+ <p>Returns the current time offset between
+ <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang monotonic time</seealso>
+ and
+ <seealso marker="time_correction#Erlang_System_Time">Erlang system time</seealso>
+ converted into the <c>time_unit</c> passed as argument.</p>
+ <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
+ time unit argument, or if called from a thread that is not a
+ scheduler thread.</p>
+ <p>See also:</p>
+ <list>
+ <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
+ <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
+ </list>
+ </desc>
+ </func>
<func>
- <name><ret>void</ret><nametext>erl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Read/Write unlock an rwlock</fsummary>
+ <name><ret>void *</ret><nametext>erl_drv_tsd_get(ErlDrvTSDKey key)</nametext></name>
+ <fsummary>Get thread specific data</fsummary>
<desc>
- <marker id="erl_drv_rwlock_rwunlock"></marker>
+ <marker id="erl_drv_tsd_get"></marker>
<p>Arguments:</p>
<taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an rwlock to read/write unlock.</item>
+ <tag><c>key</c></tag>
+ <item>A thread specific data key.</item>
</taglist>
- <p>This function read/write unlocks an rwlock. The rwlock
- currently has to be read/write locked by the calling thread.
+ <p>This function returns the thread specific data
+ associated with <c>key</c> for the calling thread.
+ If no data has been associated with <c>key</c> for
+ the calling thread, <c>NULL</c> is returned.
</p>
<p>This function is thread-safe.</p>
</desc>
@@ -2870,291 +3142,76 @@ ERL_DRV_MAP int sz
</func>
<func>
- <name><ret>void *</ret><nametext>erl_drv_tsd_get(ErlDrvTSDKey key)</nametext></name>
- <fsummary>Get thread specific data</fsummary>
+ <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name>
+ <fsummary>Get erlang error atom name from error number</fsummary>
<desc>
- <marker id="erl_drv_tsd_get"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>key</c></tag>
- <item>A thread specific data key.</item>
- </taglist>
- <p>This function returns the thread specific data
- associated with <c>key</c> for the calling thread.
- If no data has been associated with <c>key</c> for
- the calling thread, <c>NULL</c> is returned.
- </p>
- <p>This function is thread-safe.</p>
+ <marker id="erl_errno_id"></marker>
+ <p>This function returns the atom name of the erlang error,
+ given the error number in <c>error</c>. Error atoms are:
+ <c>einval</c>, <c>enoent</c>, etc. It can be used to make
+ error terms from the driver.</p>
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>erl_drv_putenv(const char *key, char *value)</nametext></name>
- <fsummary>Set the value of an environment variable</fsummary>
+ <name><ret>int</ret><nametext>remove_driver_entry(ErlDrvEntry *de)</nametext></name>
+ <fsummary>Remove a driver entry</fsummary>
<desc>
- <marker id="erl_drv_putenv"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>key</c></tag>
- <item>A null terminated string containing the
- name of the environment variable.</item>
- <tag><c>value</c></tag>
- <item>A null terminated string containing the
- new value of the environment variable.</item>
- </taglist>
- <p>This function sets the value of an environment variable.
- It returns <c>0</c> on success, and a value <c>!= 0</c> on
- failure.
- </p>
- <note><p>The result of passing the empty string ("") as a value
- is platform dependent. On some platforms the value of the
- variable is set to the empty string, on others, the
- environment variable is removed.</p>
- </note>
- <warning><p>Do <em>not</em> use libc's <c>putenv</c> or similar
- C library interfaces from a driver.
- </p></warning>
- <p>This function is thread-safe.</p>
+ <marker id="remove_driver_entry"></marker>
+ <p>This function removes a driver entry <c>de</c> previously
+ added with <c>add_driver_entry</c>.</p>
+ <p>Driver entries added by the <c>erl_ddll</c> erlang interface can
+ not be removed by using this interface.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>erl_drv_getenv(const char *key, char *value, size_t *value_size)</nametext></name>
- <fsummary>Get the value of an environment variable</fsummary>
+ <name><ret>void</ret><nametext>set_busy_port(ErlDrvPort port, int on)</nametext></name>
+ <fsummary>Signal or unsignal port as busy</fsummary>
<desc>
- <marker id="erl_drv_getenv"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>key</c></tag>
- <item>A null terminated string containing the
- name of the environment variable.</item>
- <tag><c>value</c></tag>
- <item>A pointer to an output buffer.</item>
- <tag><c>value_size</c></tag>
- <item>A pointer to an integer. The integer is both used for
- passing input and output sizes (see below).
- </item>
- </taglist>
- <p>This function retrieves the value of an environment variable.
- When called, <c>*value_size</c> should contain the size of
- the <c>value</c> buffer. On success <c>0</c> is returned,
- the value of the environment variable has been written to
- the <c>value</c> buffer, and <c>*value_size</c> contains the
- string length (excluding the terminating null character) of
- the value written to the <c>value</c> buffer. On failure,
- i.e., no such environment variable was found, a value less than
- <c>0</c> is returned. When the size of the <c>value</c>
- buffer is too small, a value greater than <c>0</c> is returned
- and <c>*value_size</c> has been set to the buffer size needed.
+ <marker id="set_busy_port"></marker>
+ <p>This function set and unset the busy state of the port. If
+ <c>on</c> is non-zero, the port is set to busy, if it's zero the port
+ is set to not busy. You typically want to combine
+ this feature with the <seealso marker="#erl_drv_busy_msgq_limits">busy
+ port message queue</seealso> functionality.</p>
+ <p>Processes sending command data to the port will be suspended
+ if either the port is busy or if the port message queue
+ is busy. Suspended processes will be resumed when neither the
+ port is busy, nor the port message queue is busy. Command data
+ is in this context data passed to the port using either
+ <c>Port ! {Owner, {command, Data}}</c>, or
+ <c>port_command/[2,3]</c>.</p>
+ <p>If the
+ <seealso marker="driver_entry#driver_flags"><![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso>
+ has been set in the
+ <seealso marker="driver_entry">driver_entry</seealso>,
+ data can be forced into the driver via
+ <seealso marker="erlang#port_command/3">port_command(Port, Data, [force])</seealso>
+ even though the driver has signaled that it is busy.
</p>
- <warning><p>Do <em>not</em> use libc's <c>getenv</c> or similar
- C library interfaces from a driver.
- </p></warning>
- <p>This function is thread-safe.</p>
+ <p>For information about busy port message queue functionality
+ see the documentation of the
+ <seealso marker="#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso>
+ function.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>erl_drv_consume_timeslice(ErlDrvPort port, int percent)</nametext></name>
- <fsummary>Give the runtime system a hint about how much CPU time the
- current driver callback call has consumed</fsummary>
+ <name><ret>void</ret><nametext>set_port_control_flags(ErlDrvPort port, int flags)</nametext></name>
+ <fsummary>Set flags on how to handle control entry function</fsummary>
<desc>
- <marker id="erl_drv_consume_timeslice"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>port</c></tag>
- <item>Port handle of the executing port.</item>
- <tag><c>percent</c></tag>
- <item>Approximate consumed fraction of a full
- time-slice in percent.</item>
- </taglist>
- <p>Give the runtime system a hint about how much CPU time the
- current driver callback call has consumed since last hint, or
- since the start of the callback if no previous hint has been given.
- The time is given as a fraction, in percent, of a full time-slice
- that a port is allowed to execute before it should surrender the
- CPU to other runnable ports or processes. Valid range is
- <c>[1, 100]</c>. The scheduling time-slice is not an exact entity,
- but can usually be approximated to about 1 millisecond.</p>
-
- <p>Note that it is up to the runtime system to determine if and
- how to use this information. Implementations on some platforms
- may use other means in order to determine the consumed fraction
- of the time-slice. Lengthy driver callbacks should regardless of
- this frequently call the <c>erl_drv_consume_timeslice()</c>
- function in order to determine if it is allowed to continue
- execution or not.</p>
-
- <p><c>erl_drv_consume_timeslice()</c> returns a non-zero value
- if the time-slice has been exhausted, and zero if the callback is
- allowed to continue execution. If a non-zero value is
- returned the driver callback should return as soon as possible in
- order for the port to be able to yield.</p>
-
- <p>This function is provided to better support co-operative scheduling,
- improve system responsiveness, and to make it easier to prevent
- misbehaviors of the VM due to a port monopolizing a scheduler thread.
- It can be used when dividing length work into a number of repeated
- driver callback calls without the need to use threads. Also see the
- important <seealso marker="#WARNING">warning</seealso> text at the
- beginning of this document.</p>
+ <marker id="set_port_control_flags"></marker>
+ <p>This function sets flags for how the <seealso marker="driver_entry#control">control</seealso> driver entry
+ function will return data to the port owner process. (The
+ <c>control</c> function is called from <c>port_control/3</c>
+ in erlang.)</p>
+ <p>Currently there are only two meaningful values for
+ <c>flags</c>: 0 means that data is returned in a list, and
+ <c>PORT_CONTROL_FLAG_BINARY</c> means data is returned as
+ a binary from <c>control</c>.</p>
</desc>
</func>
-
- <func>
- <name><ret>char *</ret><nametext>erl_drv_cond_name(ErlDrvCond *cnd)</nametext></name>
- <fsummary>Get name of driver mutex.</fsummary>
- <desc>
- <marker id="erl_drv_cnd_name"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>cnd</c></tag>
- <item>A pointer to an initialized condition.</item>
- </taglist>
- <p>
- Returns a pointer to the name of the condition.
- </p>
- <note>
- <p>This function is intended for debugging purposes only.</p>
- </note>
- </desc>
- </func>
-
- <func>
- <name><ret>char *</ret><nametext>erl_drv_mutex_name(ErlDrvMutex *mtx)</nametext></name>
- <fsummary>Get name of driver mutex.</fsummary>
- <desc>
- <marker id="erl_drv_mutex_name"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>mtx</c></tag>
- <item>A pointer to an initialized mutex.</item>
- </taglist>
- <p>
- Returns a pointer to the name of the mutex.
- </p>
- <note>
- <p>This function is intended for debugging purposes only.</p>
- </note>
- </desc>
- </func>
-
- <func>
- <name><ret>char *</ret><nametext>erl_drv_rwlock_name(ErlDrvRWLock *rwlck)</nametext></name>
- <fsummary>Get name of driver mutex.</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_name"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>rwlck</c></tag>
- <item>A pointer to an initialized r/w-lock.</item>
- </taglist>
- <p>
- Returns a pointer to the name of the r/w-lock.
- </p>
- <note>
- <p>This function is intended for debugging purposes only.</p>
- </note>
- </desc>
- </func>
-
- <func>
- <name><ret>char *</ret><nametext>erl_drv_thread_name(ErlDrvTid tid)</nametext></name>
- <fsummary>Get name of driver mutex.</fsummary>
- <desc>
- <marker id="erl_drv_rwlock_name"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>tid</c></tag>
- <item>A thread identifier.</item>
- </taglist>
- <p>
- Returns a pointer to the name of the thread.
- </p>
- <note>
- <p>This function is intended for debugging purposes only.</p>
- </note>
- </desc>
- </func>
-
- <func>
- <name><ret>ErlDrvTime</ret><nametext>erl_drv_monotonic_time(ErlDrvTimeUnit time_unit)</nametext></name>
- <fsummary>Get Erlang Monotonic Time</fsummary>
- <desc>
- <marker id="erl_drv_monotonic_time"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>time_unit</c></tag>
- <item>Time unit of returned value.</item>
- </taglist>
- <p>
- Returns
- <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang
- monotonic time</seealso>. Note that it is not uncommon with
- negative values.
- </p>
- <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
- time unit argument, or if called from a thread that is not a
- scheduler thread.</p>
- <p>See also:</p>
- <list>
- <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
- <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
- </list>
- </desc>
- </func>
-
- <func>
- <name><ret>ErlDrvTime</ret><nametext>erl_drv_time_offset(ErlDrvTimeUnit time_unit)</nametext></name>
- <fsummary>Get current Time Offset</fsummary>
- <desc>
- <marker id="erl_drv_time_offset"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>time_unit</c></tag>
- <item>Time unit of returned value.</item>
- </taglist>
- <p>Returns the current time offset between
- <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang monotonic time</seealso>
- and
- <seealso marker="time_correction#Erlang_System_Time">Erlang system time</seealso>
- converted into the <c>time_unit</c> passed as argument.</p>
- <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
- time unit argument, or if called from a thread that is not a
- scheduler thread.</p>
- <p>See also:</p>
- <list>
- <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
- <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
- </list>
- </desc>
- </func>
-
- <func>
- <name><ret>ErlDrvTime</ret><nametext>erl_drv_convert_time_unit(ErlDrvTime val, ErlDrvTimeUnit from, ErlDrvTimeUnit to)</nametext></name>
- <fsummary>Convert time unit of a time value</fsummary>
- <desc>
- <marker id="erl_drv_convert_time_unit"></marker>
- <p>Arguments:</p>
- <taglist>
- <tag><c>val</c></tag>
- <item>Value to convert time unit for.</item>
- <tag><c>from</c></tag>
- <item>Time unit of <c>val</c>.</item>
- <tag><c>to</c></tag>
- <item>Time unit of returned value.</item>
- </taglist>
- <p>Converts the <c>val</c> value of time unit <c>from</c> to
- the corresponding value of time unit <c>to</c>. The result is
- rounded using the floor function.</p>
- <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid
- time unit argument.</p>
- <p>See also:</p>
- <list>
- <item><seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso></item>
- <item><seealso marker="#ErlDrvTimeUnit"><c>ErlDrvTimeUnit</c></seealso></item>
- </list>
- </desc>
- </func>
-
</funcs>
<section>
<title>SEE ALSO</title>
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index f3921f1922..8ed042f6f9 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -124,6 +124,7 @@ ok
Note however that unused local stub functions will be optimized
away by the compiler causing loading of the NIF library to fail.</p>
</note>
+
<p>A loaded NIF library is tied to the Erlang module code version
that loaded it. If the module is upgraded with a new version, the
new Erlang code will have to load its own NIF library (or maybe choose not
@@ -401,7 +402,7 @@ ok
as I/O bound jobs, dirty I/O schedulers might starve ordinary
schedulers. I/O bound jobs are expected to either block waiting
for I/O, and/or spend a limited amount of time moving data.
- </p>
+ </p>
<p>
To schedule a dirty NIF for execution, the appropriate
@@ -434,7 +435,6 @@ ok
dirty schedulers need to complete before the block
operation can complete.
</p>
-
<p>
A lot of operations communicating with a process executing a
dirty NIF can, however, complete while it is executing the
@@ -442,7 +442,6 @@ ok
<c>process_info()</c>, setting its group leader,
register/unregister its name, etc.
</p>
-
<p>
Termination of a process executing a dirty NIF can only be
completed up to a certain point while it is executing the
@@ -462,7 +461,6 @@ ok
heap, and process control block will be delayed until the
dirty NIF has completed.
</p>
-
<p>Currently known issues that are planned to be fixed:</p>
<list>
<item>
@@ -756,11 +754,14 @@ typedef enum {
</section>
<funcs>
- <func><name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name>
+ <func>
+ <name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name>
<fsummary>Allocate dynamic memory</fsummary>
<desc><p>Allocate memory of <c>size</c> bytes. Return NULL if allocation failed.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_alloc_binary(size_t size, ErlNifBinary* bin)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_alloc_binary(size_t size, ErlNifBinary* bin)</nametext></name>
<fsummary>Create a new binary</fsummary>
<desc><p>Allocate a new binary of size <c>size</c>
bytes. Initialize the structure pointed to by <c>bin</c> to
@@ -773,7 +774,9 @@ typedef enum {
<p>Return true on success or false if allocation failed.</p>
</desc>
</func>
- <func><name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name>
+
+ <func>
+ <name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name>
<fsummary>Create a new environment</fsummary>
<desc><p>Allocate a new process independent environment. The environment can
be used to hold terms that is not bound to any process. Such terms can
@@ -783,17 +786,15 @@ typedef enum {
<p>Return pointer to the new environment.</p>
</desc>
</func>
- <func><name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name>
+
+ <func>
+ <name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name>
<fsummary>Allocate a memory managed resource object</fsummary>
<desc><p>Allocate a memory managed resource object of type <c>type</c> and size <c>size</c> bytes.</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_clear_env(ErlNifEnv* env)</nametext></name>
- <fsummary>Clear an environment for reuse</fsummary>
- <desc><p>Free all terms in an environment and clear it for reuse. The environment must
- have been allocated with <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>.
- </p></desc>
- </func>
- <func><name><ret>size_t</ret><nametext>enif_binary_to_term(ErlNifEnv *env, const unsigned char* data, size_t size, ERL_NIF_TERM *term, ErlNifBinaryToTerm opts)</nametext></name>
+
+ <func>
+ <name><ret>size_t</ret><nametext>enif_binary_to_term(ErlNifEnv *env, const unsigned char* data, size_t size, ERL_NIF_TERM *term, ErlNifBinaryToTerm opts)</nametext></name>
<fsummary>Create a term from the external format</fsummary>
<desc>
<p>Create a term that is the result of decoding the binary data
@@ -812,7 +813,19 @@ typedef enum {
</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name>
+
+
+ <func>
+ <name><ret>void</ret><nametext>enif_clear_env(ErlNifEnv* env)</nametext></name>
+ <fsummary>Clear an environment for reuse</fsummary>
+ <desc><p>Free all terms in an environment and clear it for reuse. The environment must
+ have been allocated with <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>.
+ </p></desc>
+ </func>
+
+
+ <func>
+ <name><ret>int</ret><nametext>enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name>
<fsummary>Compare two terms</fsummary>
<desc><p>Return an integer less than, equal to, or greater than
zero if <c>lhs</c> is found, respectively, to be less than,
@@ -820,32 +833,44 @@ typedef enum {
operators <c>==</c>, <c>/=</c>, <c>=&lt;</c>, <c>&lt;</c>,
<c>&gt;=</c> and <c>&gt;</c> (but <em>not</em> <c>=:=</c> or <c>=/=</c>).</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast">erl_drv_cond_broadcast</seealso>.
</p></desc>
</func>
- <func><name><ret>ErlNifCond *</ret><nametext>enif_cond_create(char *name)</nametext></name>
+
+ <func>
+ <name><ret>ErlNifCond *</ret><nametext>enif_cond_create(char *name)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_create">erl_drv_cond_create</seealso>.
</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_cond_destroy(ErlNifCond *cnd)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_cond_destroy(ErlNifCond *cnd)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_destroy">erl_drv_cond_destroy</seealso>.
</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_cond_signal(ErlNifCond *cnd)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_cond_signal(ErlNifCond *cnd)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_signal">erl_drv_cond_signal</seealso>.
</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_wait">erl_drv_cond_wait</seealso>.
</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_consume_timeslice(ErlNifEnv *env, int percent)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_consume_timeslice(ErlNifEnv *env, int percent)</nametext></name>
<fsummary></fsummary>
<desc><p>Give the runtime system a hint about how much CPU time the current NIF call has consumed
since last hint, or since the start of the NIF if no previous hint has been given.
@@ -869,9 +894,9 @@ typedef enum {
a number of repeated NIF-calls without the need to create threads.
See also the <seealso marker="#WARNING">warning</seealso> text at the beginning of this document.</p>
</desc>
-
</func>
+
<func>
<name><ret>ErlNifTime</ret><nametext>enif_convert_time_unit(ErlNifTime val, ErlNifTimeUnit from, ErlNifTimeUnit to)</nametext></name>
<fsummary>Convert time unit of a time value</fsummary>
@@ -911,21 +936,28 @@ typedef enum {
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)</nametext></name>
+ <func>
+ <name><ret>int</ret><nametext>enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)</nametext></name>
<fsummary></fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_equal_tids">erl_drv_equal_tids</seealso>.
</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_free(void* ptr)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_free(void* ptr)</nametext></name>
<fsummary>Free dynamic memory</fsummary>
<desc><p>Free memory allocated by <c>enif_alloc</c>.</p></desc>
</func>
- <func><name><ret>void</ret><nametext>enif_free_env(ErlNifEnv* env)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_free_env(ErlNifEnv* env)</nametext></name>
<fsummary>Free an environment allocated with enif_alloc_env</fsummary>
<desc><p>Free an environment allocated with <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>.
All terms created in the environment will be freed as well.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode)</nametext></name>
<fsummary>Get the text representation of an atom term</fsummary>
<desc><p>Write a null-terminated string, in the buffer pointed to by
<c>buf</c> of size <c>size</c>, consisting of the string
@@ -935,77 +967,102 @@ typedef enum {
<c>term</c> is not an atom with maximum length of
<c>size-1</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode)</nametext></name>
<fsummary>Get the length of atom <c>term</c></fsummary>
<desc><p>Set <c>*len</c> to the length (number of bytes excluding
terminating null character) of the atom <c>term</c> with encoding
<c>encode</c>. Return true on success or false if <c>term</c> is not an
atom.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)</nametext></name>
<fsummary>Read a floating-point number term</fsummary>
<desc><p>Set <c>*dp</c> to the floating point value of
<c>term</c>. Return true on success or false if <c>term</c> is not a float.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip)</nametext></name>
<fsummary>Read an integer term</fsummary>
<desc><p>Set <c>*ip</c> to the integer value of
<c>term</c>. Return true on success or false if <c>term</c> is not an
integer or is outside the bounds of type <c>int</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)</nametext></name>
<fsummary>Read a 64-bit integer term</fsummary>
<desc><p>Set <c>*ip</c> to the integer value of
<c>term</c>. Return true on success or false if <c>term</c> is not an
integer or is outside the bounds of a signed 64-bit integer.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid)</nametext></name>
<fsummary>Read an local pid term</fsummary>
<desc><p>If <c>term</c> is the pid of a node local process, initialize the
pid variable <c>*pid</c> from it and return true. Otherwise return false.
No check if the process is alive is done.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_local_port(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPort* port_id)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_local_port(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPort* port_id)</nametext></name>
<fsummary>Read an local port term</fsummary>
<desc><p>If <c>term</c> identifies a node local port, initialize the
port variable <c>*port_id</c> from it and return true. Otherwise return false.
No check if the port is alive is done.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)</nametext></name>
<fsummary>Get head and tail from a list</fsummary>
<desc><p>Set <c>*head</c> and <c>*tail</c> from
<c>list</c> and return true, or return false if <c>list</c> is not a
non-empty list.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)</nametext></name>
<fsummary>Get the length of list <c>term</c></fsummary>
<desc><p>Set <c>*len</c> to the length of list <c>term</c> and return true,
or return false if <c>term</c> is not a proper list.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)</nametext></name>
<fsummary>Read an long integer term</fsummary>
<desc><p>Set <c>*ip</c> to the long integer value of <c>term</c> and
return true, or return false if <c>term</c> is not an integer or is
outside the bounds of type <c>long int</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, size_t *size)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, size_t *size)</nametext></name>
<fsummary>Read the size of a map term</fsummary>
<desc><p>Set <c>*size</c> to the number of key-value pairs in the map <c>term</c> and
return true, or return false if <c>term</c> is not a map.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_map_value(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_map_value(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value)</nametext></name>
<fsummary>Get the value of a key in a map</fsummary>
<desc><p>Set <c>*value</c> to the value associated with <c>key</c> in the
map <c>map</c> and return true. Return false if <c>map</c> is not a map
or if <c>map</c> does not contain <c>key</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)</nametext></name>
+ <func>
+ <name><ret>int</ret><nametext>enif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)</nametext></name>
<fsummary>Get the pointer to a resource object</fsummary>
<desc><p>Set <c>*objp</c> to point to the resource object referred to by <c>term</c>.</p>
<p>Return true on success or false if <c>term</c> is not a handle to a resource object
of type <c>type</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_string(ErlNifEnv* env,
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_string(ErlNifEnv* env,
ERL_NIF_TERM list, char* buf, unsigned size,
ErlNifCharEncoding encode)</nametext></name>
<fsummary>Get a C-string from a list</fsummary>
@@ -1020,7 +1077,9 @@ typedef enum {
The written string is always null-terminated unless buffer
<c>size</c> is less than 1.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array)</nametext></name>
<fsummary>Inspect the elements of a tuple</fsummary>
<desc><p>If <c>term</c> is a tuple, set <c>*array</c> to point
to an array containing the elements of the tuple and set
@@ -1030,29 +1089,39 @@ typedef enum {
is zero.</p><p>Return true on success or false if <c>term</c> is not a
tuple.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_uint(ErlNifEnv* env, ERL_NIF_TERM term, unsigned int* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_uint(ErlNifEnv* env, ERL_NIF_TERM term, unsigned int* ip)</nametext></name>
<fsummary>Read an unsigned integer term</fsummary>
<desc><p>Set <c>*ip</c> to the unsigned integer value of <c>term</c> and
return true, or return false if <c>term</c> is not an unsigned integer or
is outside the bounds of type <c>unsigned int</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)</nametext></name>
<fsummary>Read an unsigned 64-bit integer term</fsummary>
<desc><p>Set <c>*ip</c> to the unsigned integer value of <c>term</c> and
return true, or return false if <c>term</c> is not an unsigned integer or
is outside the bounds of an unsigned 64-bit integer.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)</nametext></name>
<fsummary>Read an unsigned integer term</fsummary>
<desc><p>Set <c>*ip</c> to the unsigned long integer value of <c>term</c>
and return true, or return false if <c>term</c> is not an unsigned integer or is
outside the bounds of type <c>unsigned long</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_getenv(const char* key, char* value, size_t *value_size)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_getenv(const char* key, char* value, size_t *value_size)</nametext></name>
<fsummary>Get the value of an environment variable</fsummary>
<desc><p>Same as <seealso marker="erl_driver#erl_drv_getenv">erl_drv_getenv</seealso>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_has_pending_exception(ErlNifEnv* env, ERL_NIF_TERM* reason)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_has_pending_exception(ErlNifEnv* env, ERL_NIF_TERM* reason)</nametext></name>
<fsummary>Check if an exception has been raised</fsummary>
<desc><p>Return true if a pending exception is associated
with the environment <c>env</c>. If <c>reason</c> is a null pointer, ignore it.
@@ -1065,13 +1134,17 @@ typedef enum {
and <seealso marker="#enif_raise_exception">enif_raise_exception</seealso>.</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)</nametext></name>
<fsummary>Inspect the content of a binary</fsummary>
<desc><p>Initialize the structure pointed to by <c>bin</c> with
information about the binary term
<c>bin_term</c>. Return true on success or false if <c>bin_term</c> is not a binary.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_inspect_iolist_as_binary(ErlNifEnv*
+
+ <func>
+ <name><ret>int</ret><nametext>enif_inspect_iolist_as_binary(ErlNifEnv*
env, ERL_NIF_TERM term, ErlNifBinary* bin)
</nametext></name>
<fsummary>Inspect the content of an iolist</fsummary>
@@ -1082,81 +1155,115 @@ typedef enum {
iolist.</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is an atom</fsummary>
<desc><p>Return true if <c>term</c> is an atom.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a binary</fsummary>
<desc><p>Return true if <c>term</c> is a binary</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_current_process_alive(ErlNifEnv* env)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_current_process_alive(ErlNifEnv* env)</nametext></name>
<fsummary>Determine if currently executing process is alive or not.</fsummary>
<desc><p>Return true if currently executing process is currently alive; otherwise
false.</p>
<p>This function can only be used from a NIF-calling thread, and with an
environment corresponding to currently executing processes.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is an empty list</fsummary>
<desc><p>Return true if <c>term</c> is an empty list.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is an exception</fsummary>
<desc><marker id="enif_is_exception"/>
<p>Return true if <c>term</c> is an exception.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_map(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
- <fsummary>Determine if a term is a map</fsummary>
- <desc><p>Return true if <c>term</c> is a map, false otherwise.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
- <fsummary>Determine if a term is a number (integer or float)</fsummary>
- <desc><p>Return true if <c>term</c> is a number.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a fun</fsummary>
<desc><p>Return true if <c>term</c> is a fun.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_identical(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_identical(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name>
<fsummary>Erlang operator =:=</fsummary>
<desc><p>Return true if the two terms are identical. Corresponds to the
Erlang operators <c>=:=</c> and
<c>=/=</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+ <fsummary>Determine if a term is a list</fsummary>
+ <desc><p>Return true if <c>term</c> is a list.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_map(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+ <fsummary>Determine if a term is a map</fsummary>
+ <desc><p>Return true if <c>term</c> is a map, false otherwise.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+ <fsummary>Determine if a term is a number (integer or float)</fsummary>
+ <desc><p>Return true if <c>term</c> is a number.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a pid</fsummary>
<desc><p>Return true if <c>term</c> is a pid.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a port</fsummary>
<desc><p>Return true if <c>term</c> is a port.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_port_alive(ErlNifEnv* env, ErlNifPort *port_id)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_port_alive(ErlNifEnv* env, ErlNifPort *port_id)</nametext></name>
<fsummary>Determine if a local port is alive or not.</fsummary>
<desc><p>Return true if <c>port_id</c> is currently alive.</p>
<p>This function is only thread-safe when the emulator with SMP support is used.
It can only be used in a non-SMP emulator from a NIF-calling thread.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_process_alive(ErlNifEnv* env, ErlNifPid *pid)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_process_alive(ErlNifEnv* env, ErlNifPid *pid)</nametext></name>
<fsummary>Determine if a local process is alive or not.</fsummary>
<desc><p>Return true if <c>pid</c> is currently alive.</p>
<p>This function is only thread-safe when the emulator with SMP support is used.
It can only be used in a non-SMP emulator from a NIF-calling thread.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a reference</fsummary>
<desc><p>Return true if <c>term</c> is a reference.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
<fsummary>Determine if a term is a tuple</fsummary>
<desc><p>Return true if <c>term</c> is a tuple.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name>
- <fsummary>Determine if a term is a list</fsummary>
- <desc><p>Return true if <c>term</c> is a list.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_keep_resource(void* obj)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_keep_resource(void* obj)</nametext></name>
<fsummary>Add a reference to a resource object</fsummary>
<desc><p>Add a reference to resource object <c>obj</c> obtained from
<seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.
@@ -1164,7 +1271,9 @@ typedef enum {
a call to <seealso marker="#enif_release_resource">enif_release_resource</seealso>
before the object will be destructed.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom(ErlNifEnv* env, const char* name)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom(ErlNifEnv* env, const char* name)</nametext></name>
<fsummary>Create an atom term</fsummary>
<desc><p>Create an atom term from the null-terminated C-string <c>name</c>
with iso-latin-1 encoding. If the length of <c>name</c> exceeds the maximum length
@@ -1172,7 +1281,9 @@ typedef enum {
<seealso marker="#enif_make_badarg">enif_make_badarg</seealso>.
</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)</nametext></name>
<fsummary>Create an atom term</fsummary>
<desc><p>Create an atom term from the string <c>name</c> with length <c>len</c>.
Null-characters are treated as any other characters. If <c>len</c> is greater than the maximum length
@@ -1180,7 +1291,9 @@ typedef enum {
<seealso marker="#enif_make_badarg">enif_make_badarg</seealso>.
</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_badarg(ErlNifEnv* env)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_badarg(ErlNifEnv* env)</nametext></name>
<fsummary>Make a badarg exception</fsummary>
<desc><p>Make a badarg exception to be returned from a NIF, and associate
it with the environment <c>env</c>. Once a NIF or any function
@@ -1200,27 +1313,35 @@ typedef enum {
requirement is now lifted as the return value from the NIF is ignored
if <c>enif_make_badarg</c> has been invoked.</p></note></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)</nametext></name>
<fsummary>Make a binary term</fsummary>
<desc><p>Make a binary term from <c>bin</c>. Any ownership of
the binary data will be transferred to the created term and
<c>bin</c> should be considered read-only for the rest of the NIF
call and then as released.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)</nametext></name>
<fsummary>Make a copy of a term</fsummary>
<desc><p>Make a copy of term <c>src_term</c>. The copy will be created in
environment <c>dst_env</c>. The source term may be located in any
environment.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_double(ErlNifEnv* env, double d)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_double(ErlNifEnv* env, double d)</nametext></name>
<fsummary>Create a floating-point term</fsummary>
<desc><p>Create a floating-point term from a <c>double</c>. If the <c>double</c> argument is
not finite or is NaN, <c>enif_make_double</c> invokes
<seealso marker="#enif_make_badarg">enif_make_badarg</seealso>.
</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)</nametext></name>
<fsummary>Create an existing atom term</fsummary>
<desc><p>Try to create the term of an already existing atom from
the null-terminated C-string <c>name</c> with encoding
@@ -1230,7 +1351,9 @@ typedef enum {
allowed for an atom (255 characters), <c>enif_make_existing_atom</c>
returns false.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)</nametext></name>
<fsummary>Create an existing atom term</fsummary>
<desc><p>Try to create the term of an already existing atom from the
string <c>name</c> with length <c>len</c> and encoding
@@ -1240,21 +1363,29 @@ typedef enum {
than the maximum length allowed for an atom (255 characters),
<c>enif_make_existing_atom_len</c> returns false.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int(ErlNifEnv* env, int i)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int(ErlNifEnv* env, int i)</nametext></name>
<fsummary>Create an integer term</fsummary>
<desc><p>Create an integer term.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)</nametext></name>
<fsummary>Create an integer term</fsummary>
<desc><p>Create an integer term from a signed 64-bit integer.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list(ErlNifEnv* env, unsigned cnt, ...)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list(ErlNifEnv* env, unsigned cnt, ...)</nametext></name>
<fsummary>Create a list term</fsummary>
<desc><p>Create an ordinary list term of length <c>cnt</c>. Expects
<c>cnt</c> number of arguments (after <c>cnt</c>) of type ERL_NIF_TERM as the
elements of the list. An empty list is returned if <c>cnt</c> is 0.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name>
@@ -1269,34 +1400,28 @@ typedef enum {
<c>enif_make_list</c> to get a compile time error if the number of
arguments does not match.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_cell(ErlNifEnv* env, ERL_NIF_TERM head, ERL_NIF_TERM tail)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_cell(ErlNifEnv* env, ERL_NIF_TERM head, ERL_NIF_TERM tail)</nametext></name>
<fsummary>Create a list cell</fsummary>
<desc><p>Create a list cell <c>[head | tail]</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name>
<fsummary>Create a list term from an array</fsummary>
<desc><p>Create an ordinary list containing the elements of array <c>arr</c>
of length <c>cnt</c>. An empty list is returned if <c>cnt</c> is 0.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_long(ErlNifEnv* env, long int i)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_long(ErlNifEnv* env, long int i)</nametext></name>
<fsummary>Create an integer term from a long int</fsummary>
<desc><p>Create an integer term from a <c>long int</c>.</p></desc>
</func>
- <func><name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name>
- <fsummary>Allocate and create a new binary term</fsummary>
- <desc><p>Allocate a binary of size <c>size</c> bytes and create an owning
- term. The binary data is mutable until the calling NIF returns. This is a
- quick way to create a new binary without having to use
- <seealso marker="#ErlNifBinary">ErlNifBinary</seealso>. The drawbacks are
- that the binary can not be kept between NIF calls and it can not be
- reallocated.</p><p>Return a pointer to the raw binary data and set
- <c>*termp</c> to the binary term.</p></desc>
- </func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_new_map(ErlNifEnv* env)</nametext></name>
- <fsummary>Make an empty map term</fsummary>
- <desc><p>Make an empty map term.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_make_map_put(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_map_put(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out)</nametext></name>
<fsummary>Insert key-value pair in map</fsummary>
<desc><p>Make a copy of map <c>map_in</c> and insert <c>key</c> with
<c>value</c>. If <c>key</c> already exists in <c>map_in</c>, the old
@@ -1305,15 +1430,9 @@ typedef enum {
<c>map_in</c> is not a map.</p>
<p>The <c>map_in</c> term must belong to the environment <c>env</c>.</p></desc>
</func>
- <func><name><ret>int</ret><nametext>enif_make_map_update(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, ERL_NIF_TERM* map_out)</nametext></name>
- <fsummary>Replace value for key in map</fsummary>
- <desc><p>Make a copy of map <c>map_in</c> and replace the old associated
- value for <c>key</c> with <c>new_value</c>. If successful set
- <c>*map_out</c> to the new map and return true. Return false if
- <c>map_in</c> is not a map or if it does no contain <c>key</c>.</p>
- <p>The <c>map_in</c> term must belong to the environment <c>env</c>.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_make_map_remove(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_map_remove(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out)</nametext></name>
<fsummary>Remove key from map</fsummary>
<desc><p>If map <c>map_in</c> contains <c>key</c>, make a copy of
<c>map_in</c> in <c>*map_out</c> and remove <c>key</c> and associated
@@ -1322,15 +1441,49 @@ typedef enum {
<c>map_in</c> is not a map.</p>
<p>The <c>map_in</c> term must belong to the environment <c>env</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_map_update(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, ERL_NIF_TERM* map_out)</nametext></name>
+ <fsummary>Replace value for key in map</fsummary>
+ <desc><p>Make a copy of map <c>map_in</c> and replace the old associated
+ value for <c>key</c> with <c>new_value</c>. If successful set
+ <c>*map_out</c> to the new map and return true. Return false if
+ <c>map_in</c> is not a map or if it does no contain <c>key</c>.</p>
+ <p>The <c>map_in</c> term must belong to the environment <c>env</c>.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name>
+ <fsummary>Allocate and create a new binary term</fsummary>
+ <desc><p>Allocate a binary of size <c>size</c> bytes and create an owning
+ term. The binary data is mutable until the calling NIF returns. This is a
+ quick way to create a new binary without having to use
+ <seealso marker="#ErlNifBinary">ErlNifBinary</seealso>. The drawbacks are
+ that the binary can not be kept between NIF calls and it can not be
+ reallocated.</p><p>Return a pointer to the raw binary data and set
+ <c>*termp</c> to the binary term.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_new_map(ErlNifEnv* env)</nametext></name>
+ <fsummary>Make an empty map term</fsummary>
+ <desc><p>Make an empty map term.</p></desc>
+ </func>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid)</nametext></name>
<fsummary>Make a pid term</fsummary>
<desc><p>Make a pid term from <c>*pid</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ref(ErlNifEnv* env)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ref(ErlNifEnv* env)</nametext></name>
<fsummary>Create a reference</fsummary>
<desc><p>Create a reference like <seealso marker="erlang#make_ref-0">erlang:make_ref/0</seealso>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource(ErlNifEnv* env, void* obj)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource(ErlNifEnv* env, void* obj)</nametext></name>
<fsummary>Create an opaque handle to a resource object</fsummary>
<desc><p>Create an opaque handle to a memory managed resource object
obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.
@@ -1347,7 +1500,9 @@ typedef enum {
same node. Other operations such as matching or <c>term_to_binary</c>
will have unpredictable (but harmless) results.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource_binary(ErlNifEnv* env, void* obj, const void* data, size_t size)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource_binary(ErlNifEnv* env, void* obj, const void* data, size_t size)</nametext></name>
<fsummary>Create a custom binary term</fsummary>
<desc><p>Create a binary term that is memory managed by a resource object
<c>obj</c> obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.
@@ -1365,7 +1520,9 @@ typedef enum {
<seealso marker="#enif_release_resource">enif_release_resource</seealso>.</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, ERL_NIF_TERM *list_out)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, ERL_NIF_TERM *list_out)</nametext></name>
<fsummary>Create the reverse of a list</fsummary>
<desc><p>Set <c>*list_out</c> to the reverse list of the list <c>list_in</c> and return true,
or return false if <c>list_in</c> is not a list. This function should only be used on
@@ -1373,18 +1530,24 @@ typedef enum {
nif returns.</p>
<p>The <c>list_in</c> term must belong to the environment <c>env</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding)</nametext></name>
<fsummary>Create a string</fsummary>
<desc><p>Create a list containing the characters of the
null-terminated string <c>string</c> with encoding <seealso marker="#ErlNifCharEncoding">encoding</seealso>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding)</nametext></name>
<fsummary>Create a string</fsummary>
<desc><p>Create a list containing the characters of the string <c>string</c> with
length <c>len</c> and encoding <seealso marker="#ErlNifCharEncoding">encoding</seealso>.
Null-characters are treated as any other characters.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_sub_binary(ErlNifEnv*
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_sub_binary(ErlNifEnv*
env, ERL_NIF_TERM bin_term, size_t pos, size_t size)</nametext></name>
<fsummary>Make a subbinary term</fsummary>
<desc><p>Make a subbinary of binary <c>bin_term</c>, starting at
@@ -1393,13 +1556,17 @@ typedef enum {
<c>pos+size</c> must be less or equal to the number of whole
bytes in <c>bin_term</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)</nametext></name>
<fsummary>Create a tuple term</fsummary>
<desc><p>Create a tuple term of arity <c>cnt</c>. Expects
<c>cnt</c> number of arguments (after <c>cnt</c>) of type ERL_NIF_TERM as the
elements of the tuple.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name>
@@ -1414,19 +1581,32 @@ typedef enum {
<c>enif_make_tuple</c> to get a compile time error if the number of
arguments does not match.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name>
<fsummary>Create a tuple term from an array</fsummary>
<desc><p>Create a tuple containing the elements of array <c>arr</c>
of length <c>cnt</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint(ErlNifEnv* env, unsigned int i)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint(ErlNifEnv* env, unsigned int i)</nametext></name>
<fsummary>Create an unsigned integer term</fsummary>
<desc><p>Create an integer term from an <c>unsigned int</c>.</p></desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)</nametext></name>
<fsummary>Create an unsigned integer term</fsummary>
<desc><p>Create an integer term from an unsigned 64-bit integer.</p></desc>
</func>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ulong(ErlNifEnv* env, unsigned long i)</nametext></name>
+ <fsummary>Create an integer term from an unsigned long int</fsummary>
+ <desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc>
+ </func>
+
<func>
<name><ret>ERL_NIF_TERM</ret><nametext>enif_make_unique_integer(ErlNifEnv *env, ErlNifUniqueInteger properties)</nametext></name>
<fsummary></fsummary>
@@ -1444,11 +1624,9 @@ typedef enum {
</p>
</desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ulong(ErlNifEnv* env, unsigned long i)</nametext></name>
- <fsummary>Create an integer term from an unsigned long int</fsummary>
- <desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc>
- </func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_create(ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry entry)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_create(ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry entry)</nametext></name>
<fsummary>Create a map iterator</fsummary>
<desc><p>Create an iterator for the map <c>map</c> by initializing the
structure pointed to by <c>iter</c>. The <c>entry</c> argument determines
@@ -1477,42 +1655,66 @@ enif_map_iterator_destroy(env, &amp;iter);
</note>
</desc>
</func>
- <func><name><ret>void</ret><nametext>enif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
+
+ <func>
+ <name><ret>void</ret><nametext>enif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
<fsummary>Destroy a map iterator</fsummary>
- <desc><p>Destroy a map iterator created by
+ <desc>
+ <p>Destroy a map iterator created by
<seealso marker="#enif_map_iterator_create">enif_map_iterator_create</seealso>.
- </p></desc>
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_get_pair(ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_get_pair(ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value)</nametext></name>
<fsummary>Get key and value at current map iterator position</fsummary>
- <desc><p>Get key and value terms at current map iterator position.
+ <desc>
+ <p>Get key and value terms at current map iterator position.
On success set <c>*key</c> and <c>*value</c> and return true.
Return false if the iterator is positioned at head (before first entry)
- or tail (beyond last entry).</p></desc>
+ or tail (beyond last entry).</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_is_head(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_is_head(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
<fsummary>Check if map iterator is positioned before first</fsummary>
- <desc><p>Return true if map iterator <c>iter</c> is positioned
- before first entry.</p></desc>
+ <desc>
+ <p>Return true if map iterator <c>iter</c> is positioned
+ before first entry.</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_is_tail(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_is_tail(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
<fsummary>Check if map iterator is positioned after last</fsummary>
- <desc><p>Return true if map iterator <c>iter</c> is positioned
- after last entry.</p></desc>
+ <desc>
+ <p>Return true if map iterator <c>iter</c> is positioned
+ after last entry.</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
<fsummary>Increment map iterator to point to next entry</fsummary>
- <desc><p>Increment map iterator to point to next key-value entry.
+ <desc>
+ <p>Increment map iterator to point to next key-value entry.
Return true if the iterator is now positioned at a valid key-value entry,
or false if the iterator is positioned at the tail (beyond the last
- entry).</p></desc>
+ entry).</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
+
+ <func>
+ <name><ret>int</ret><nametext>enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)</nametext></name>
<fsummary>Decrement map iterator to point to previous entry</fsummary>
- <desc><p>Decrement map iterator to point to previous key-value entry.
+ <desc>
+ <p>Decrement map iterator to point to previous key-value entry.
Return true if the iterator is now positioned at a valid key-value entry,
or false if the iterator is positioned at the head (before the first
- entry).</p></desc>
+ entry).</p>
+ </desc>
</func>
<func>
@@ -1541,41 +1743,74 @@ enif_map_iterator_destroy(env, &amp;iter);
</desc>
</func>
- <func><name><ret>ErlNifMutex *</ret><nametext>enif_mutex_create(char *name)</nametext></name>
+ <func>
+ <name><ret>ErlNifMutex *</ret>
+ <nametext>enif_mutex_create(char *name)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_create">erl_drv_mutex_create</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_mutex_create">erl_drv_mutex_create</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_mutex_destroy(ErlNifMutex *mtx)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_mutex_destroy(ErlNifMutex *mtx)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_destroy">erl_drv_mutex_destroy</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_mutex_destroy">erl_drv_mutex_destroy</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_mutex_lock(ErlNifMutex *mtx)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_mutex_lock(ErlNifMutex *mtx)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_lock">erl_drv_mutex_lock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_mutex_lock">erl_drv_mutex_lock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_mutex_trylock(ErlNifMutex *mtx)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_mutex_trylock(ErlNifMutex *mtx)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_trylock">erl_drv_mutex_trylock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_mutex_trylock">erl_drv_mutex_trylock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_mutex_unlock(ErlNifMutex *mtx)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_mutex_unlock(ErlNifMutex *mtx)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock">erl_drv_mutex_unlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock">erl_drv_mutex_unlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_now_time(ErlNifEnv *env)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret>
+ <nametext>enif_now_time(ErlNifEnv *env)</nametext></name>
<fsummary></fsummary>
- <desc><p>Retuns an <seealso marker="erlang#now-0">erlang:now()</seealso> timestamp.
- The enif_now_time function is <em>deprecated</em>.</p></desc>
+ <desc>
+ <p>Retuns an <seealso marker="erlang#now-0">erlang:now()</seealso> timestamp.
+ The enif_now_time function is <em>deprecated</em>.</p>
+ </desc>
</func>
- <func><name><ret>ErlNifResourceType *</ret><nametext>enif_open_resource_type(ErlNifEnv* env,
+
+ <func>
+ <name><ret>ErlNifResourceType *</ret>
+ <nametext>enif_open_resource_type(ErlNifEnv* env,
const char* module_str, const char* name,
ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext></name>
<fsummary>Create or takeover a resource type</fsummary>
- <desc><p>Create or takeover a resource type identified by the string
+ <desc>
+ <p>Create or takeover a resource type identified by the string
<c>name</c> and give it the destructor function pointed to by <seealso marker="#ErlNifResourceDtor">dtor</seealso>.
Argument <c>flags</c> can have the following values:</p>
<taglist>
@@ -1600,7 +1835,10 @@ enif_map_iterator_destroy(env, &amp;iter);
and <seealso marker="#upgrade">upgrade</seealso>.</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_port_command(ErlNifEnv* env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_port_command(ErlNifEnv* env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)</nametext></name>
<fsummary>Send a port_command to to_port</fsummary>
<desc>
<p>This function works the same as <seealso marker="erlang#port_command-2">erlang:port_command/2</seealso>
@@ -1630,15 +1868,24 @@ enif_map_iterator_destroy(env, &amp;iter);
<p>See also: <seealso marker="#enif_get_local_port"><c>enif_get_local_port</c></seealso>.</p>
</desc>
</func>
- <func><name><ret>void *</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name>
+
+ <func>
+ <name><ret>void *</ret>
+ <nametext>enif_priv_data(ErlNifEnv* env)</nametext></name>
<fsummary>Get the private data of a NIF library</fsummary>
- <desc><p>Return the pointer to the private data that was set by <c>load</c>,
+ <desc>
+ <p>Return the pointer to the private data that was set by <c>load</c>,
<c>reload</c> or <c>upgrade</c>.</p>
- <p>Was previously named <c>enif_get_data</c>.</p></desc>
+ <p>Was previously named <c>enif_get_data</c>.</p>
+ </desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_raise_exception(ErlNifEnv* env, ERL_NIF_TERM reason)</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret>
+ <nametext>enif_raise_exception(ErlNifEnv* env, ERL_NIF_TERM reason)</nametext></name>
<fsummary>Raise a NIF error exception</fsummary>
- <desc><p>Create an error exception with the term <c>reason</c> to be returned from a NIF,
+ <desc>
+ <p>Create an error exception with the term <c>reason</c> to be returned from a NIF,
and associate it with the environment <c>env</c>. Once a NIF or any function it calls
invokes <c>enif_raise_exception</c>, the runtime ensures that the exception it creates
is raised when the NIF returns, even if the NIF attempts to return a non-exception
@@ -1647,71 +1894,130 @@ enif_map_iterator_destroy(env, &amp;iter);
to <seealso marker="#enif_is_exception">enif_is_exception</seealso>, but
not to any other NIF API function.</p>
<p>See also: <seealso marker="#enif_has_pending_exception">enif_has_pending_exception</seealso>
- and <seealso marker="#enif_make_badarg">enif_make_badarg</seealso>.</p></desc>
+ and <seealso marker="#enif_make_badarg">enif_make_badarg</seealso>.</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_realloc_binary(ErlNifBinary* bin, size_t size)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_realloc_binary(ErlNifBinary* bin, size_t size)</nametext></name>
<fsummary>Change the size of a binary</fsummary>
- <desc><p>Change the size of a binary <c>bin</c>. The source binary
+ <desc>
+ <p>Change the size of a binary <c>bin</c>. The source binary
may be read-only, in which case it will be left untouched and
a mutable copy is allocated and assigned to <c>*bin</c>. Return true on success,
- false if memory allocation failed.</p></desc>
+ false if memory allocation failed.</p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_release_binary(ErlNifBinary* bin)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_release_binary(ErlNifBinary* bin)</nametext></name>
<fsummary>Release a binary</fsummary>
- <desc><p>Release a binary obtained from <c>enif_alloc_binary</c>.</p></desc>
+ <desc>
+ <p>Release a binary obtained from <c>enif_alloc_binary</c>.</p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_release_resource(void* obj)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_release_resource(void* obj)</nametext></name>
<fsummary>Release a resource object</fsummary>
- <desc><p>Remove a reference to resource object <c>obj</c>obtained from
+ <desc>
+ <p>Remove a reference to resource object <c>obj</c>obtained from
<seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.
The resource object will be destructed when the last reference is removed.
Each call to <c>enif_release_resource</c> must correspond to a previous
call to <c>enif_alloc_resource</c> or
<seealso marker="#enif_keep_resource">enif_keep_resource</seealso>.
References made by <seealso marker="#enif_make_resource">enif_make_resource</seealso>
- can only be removed by the garbage collector.</p></desc>
+ can only be removed by the garbage collector.</p>
+ </desc>
</func>
- <func><name><ret>ErlNifRWLock *</ret><nametext>enif_rwlock_create(char *name)</nametext></name>
+
+ <func>
+ <name><ret>ErlNifRWLock *</ret>
+ <nametext>enif_rwlock_create(char *name)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create">erl_drv_rwlock_create</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create">erl_drv_rwlock_create</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_rwlock_destroy(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_rwlock_destroy(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_destroy">erl_drv_rwlock_destroy</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_destroy">erl_drv_rwlock_destroy</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_rwlock_rlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_rwlock_rlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rlock">erl_drv_rwlock_rlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rlock">erl_drv_rwlock_rlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_rwlock_runlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_rwlock_runlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_runlock">erl_drv_rwlock_runlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_runlock">erl_drv_rwlock_runlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_rwlock_rwlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_rwlock_rwlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwlock">erl_drv_rwlock_rwlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwlock">erl_drv_rwlock_rwlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_rwlock_rwunlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_rwlock_rwunlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwunlock">erl_drv_rwlock_rwunlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwunlock">erl_drv_rwlock_rwunlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_rwlock_tryrlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_rwlock_tryrlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrlock">erl_drv_rwlock_tryrlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrlock">erl_drv_rwlock_tryrlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_rwlock_tryrwlock(ErlNifRWLock *rwlck)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_rwlock_tryrwlock(ErlNifRWLock *rwlck)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_schedule_nif(ErlNifEnv* env, const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM argv[])</nametext></name>
+
+ <func>
+ <name><ret>ERL_NIF_TERM</ret>
+ <nametext>enif_schedule_nif(ErlNifEnv* env, const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM argv[])</nametext></name>
<fsummary>Schedule a NIF for execution</fsummary>
<desc>
<p>Schedule NIF <c>fp</c> to execute. This function allows an application to break up long-running
@@ -1736,14 +2042,23 @@ enif_map_iterator_destroy(env, &amp;iter);
return value and use it for further operations.</p>
</desc>
</func>
- <func><name><ret>ErlNifPid *</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name>
+
+ <func>
+ <name><ret>ErlNifPid *</ret>
+ <nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name>
<fsummary>Get the pid of the calling process</fsummary>
- <desc><p>Initialize the pid variable <c>*pid</c> to represent the
- calling process. Return <c>pid</c>.</p></desc>
+ <desc>
+ <p>Initialize the pid variable <c>*pid</c> to represent the
+ calling process. Return <c>pid</c>.</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_send(ErlNifEnv* env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_send(ErlNifEnv* env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)</nametext></name>
<fsummary>Send a message to a process</fsummary>
- <desc><p>Send a message to a process.</p>
+ <desc>
+ <p>Send a message to a process.</p>
<taglist>
<tag><c>env</c></tag>
<item>The environment of the calling process. Must be NULL if and
@@ -1772,13 +2087,20 @@ enif_map_iterator_destroy(env, &amp;iter);
erts-8.0 (OTP 19).</p></note>
</desc>
</func>
- <func><name><ret>unsigned</ret><nametext>enif_sizeof_resource(void* obj)</nametext></name>
+
+ <func>
+ <name><ret>unsigned</ret>
+ <nametext>enif_sizeof_resource(void* obj)</nametext></name>
<fsummary>Get the byte size of a resource object</fsummary>
- <desc><p>Get the byte size of a resource object <c>obj</c> obtained by
- <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.</p></desc>
+ <desc>
+ <p>Get the byte size of a resource object <c>obj</c> obtained by
+ <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.</p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_snprintf(char *str, size_t size, const char *format, ...)</nametext></name>
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_snprintf(char *str, size_t size, const char *format, ...)</nametext></name>
<fsummary>Format strings and Erlang terms</fsummary>
<desc>
<p>Similar to <c>snprintf</c> but this format string also accepts <c>"%T"</c> which formats Erlang terms.
@@ -1787,12 +2109,18 @@ enif_map_iterator_destroy(env, &amp;iter);
</func>
<func>
- <name><ret>void</ret><nametext>enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)</nametext></name>
+ <name><ret>void</ret>
+ <nametext>enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)</nametext></name>
<fsummary>Get information about the Erlang runtime system</fsummary>
- <desc><p>Same as <seealso marker="erl_driver#driver_system_info">driver_system_info</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#driver_system_info">driver_system_info</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_term_to_binary(ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_term_to_binary(ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)</nametext></name>
<fsummary>Convert a term to the external format</fsummary>
<desc>
<p>Allocates a new binary with <seealso marker="#enif_alloc_binary">enif_alloc_binary</seealso>
@@ -1804,37 +2132,70 @@ enif_map_iterator_destroy(env, &amp;iter);
</p>
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_thread_create(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_thread_create(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_create">erl_drv_thread_create</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_create">erl_drv_thread_create</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_thread_exit(void *resp)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_thread_exit(void *resp)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_exit">erl_drv_thread_exit</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_exit">erl_drv_thread_exit</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_thread_join(ErlNifTid, void **respp)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_thread_join(ErlNifTid, void **respp)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_join">erl_drv_thread_join </seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_join">erl_drv_thread_join </seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>ErlNifThreadOpts *</ret><nametext>enif_thread_opts_create(char *name)</nametext></name>
+
+ <func>
+ <name><ret>ErlNifThreadOpts *</ret>
+ <nametext>enif_thread_opts_create(char *name)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create">erl_drv_thread_opts_create</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create">erl_drv_thread_opts_create</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_thread_opts_destroy(ErlNifThreadOpts *opts)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_thread_opts_destroy(ErlNifThreadOpts *opts)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_destroy">erl_drv_thread_opts_destroy</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_destroy">erl_drv_thread_opts_destroy</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>ErlNifTid</ret><nametext>enif_thread_self(void)</nametext></name>
+
+ <func>
+ <name><ret>ErlNifTid</ret>
+ <nametext>enif_thread_self(void)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_self">erl_drv_thread_self</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_thread_self">erl_drv_thread_self</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>int</ret><nametext>enif_thread_type(void)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_thread_type(void)</nametext></name>
<fsummary>Determine type of current thread</fsummary>
<desc>
<p>Determine the type of currently executing thread. A positive value
@@ -1853,8 +2214,10 @@ enif_map_iterator_destroy(env, &amp;iter);
</taglist>
</desc>
</func>
+
<func>
- <name><ret>ErlNifTime</ret><nametext>enif_time_offset(ErlNifTimeUnit time_unit)</nametext></name>
+ <name><ret>ErlNifTime</ret>
+ <nametext>enif_time_offset(ErlNifTimeUnit time_unit)</nametext></name>
<fsummary>Get current Time Offset</fsummary>
<desc>
<marker id="enif_time_offset"></marker>
@@ -1878,25 +2241,44 @@ enif_map_iterator_destroy(env, &amp;iter);
</desc>
</func>
- <func><name><ret>int</ret><nametext>enif_tsd_key_create(char *name, ErlNifTSDKey *key)</nametext></name>
+ <func>
+ <name><ret>void *</ret>
+ <nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_create">erl_drv_tsd_key_create</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_tsd_get">erl_drv_tsd_get</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_tsd_key_destroy(ErlNifTSDKey key)</nametext></name>
+
+ <func>
+ <name><ret>int</ret>
+ <nametext>enif_tsd_key_create(char *name, ErlNifTSDKey *key)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_create">erl_drv_tsd_key_create</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void *</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_tsd_key_destroy(ErlNifTSDKey key)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_get">erl_drv_tsd_get</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy</seealso>.
+ </p>
+ </desc>
</func>
- <func><name><ret>void</ret><nametext>enif_tsd_set(ErlNifTSDKey key, void *data)</nametext></name>
+
+ <func>
+ <name><ret>void</ret>
+ <nametext>enif_tsd_set(ErlNifTSDKey key, void *data)</nametext></name>
<fsummary></fsummary>
- <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_set">erl_drv_tsd_set</seealso>.
- </p></desc>
+ <desc>
+ <p>Same as <seealso marker="erl_driver#erl_drv_tsd_set">erl_drv_tsd_set</seealso>.
+ </p>
+ </desc>
</func>
</funcs>
<section>
diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml
index 7841fdfd63..e2852ce49d 100644
--- a/erts/doc/src/erl_tracer.xml
+++ b/erts/doc/src/erl_tracer.xml
@@ -169,83 +169,38 @@
is important that it is both fast and side effect free.</p>
</desc>
</func>
- <func>
- <name>Module:trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
- <fsummary>Check if a trace event should be generated.</fsummary>
- <type>
- <v>TraceTag = <seealso marker="#type-trace_tag">trace_tag()</seealso></v>
- <v>TracerState = term()</v>
- <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>FirstTraceTerm = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
- </type>
- <desc>
- <p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled/3">Module:enabled/3</seealso>
- callback returned <c>trace</c>. In it any side effects needed by
- the tracer should be done. The tracepoint payload is located in
- the <c>TraceTerm</c>. The content of the TraceTerm depends on which
- <c>TraceTag</c> has been triggered.
- The <c>TraceTerm</c> corresponds to the
- fourth element in the trace tuples described in
- <seealso marker="erlang#trace_3_trace_messages">erlang:trace/3</seealso>.
- If the trace tuple has five elements, the fifth element will be sent as
- the <c>extra</c> value in the <c>Opts</c> maps.</p>
- </desc>
- </func>
- <func>
- <name name="trace">Module:trace(seq_trace, TracerState, Label, SeqTraceInfo, Opts) -> Result</name>
- <fsummary>Check if a sequence trace event should be generated.</fsummary>
- <type>
- <v>TracerState = term()</v>
- <v>Label = term()</v>
- <v>SeqTraceInfo = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
- </type>
- <desc>
- <p>The <c>TraceTag</c> <c>seq_trace</c> is handled a little bit
- differently. There is not <c>Tracee</c> for seq_trace, instead the
- <c>Label</c> associated with the seq_trace event is given.
- For more info on what <c>Label</c> and <c>SeqTraceInfo</c> can be
- see the <seealso marker="kernel:seq_trace">seq_trace</seealso> manual.</p>
- </desc>
- </func>
<func>
- <name>Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:enabled_call(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag_procs()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_call">trace_tag_call()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
<v>Result = trace | discard | remove</v>
</type>
<desc>
<p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>procs</c></seealso>
+ <seealso marker="erlang#trace-3"><c>call | return_to</c></seealso>
is triggered.</p>
- <p>If <c>enabled_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>If <c>enabled_call/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:trace_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <name>Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>FirstTraceTerm = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
+ <v>Result = trace | discard | remove</v>
</type>
<desc>
- <p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_procs/3">Module:enabled_procs/3</seealso>
- callback returned <c>trace</c>.</p>
- <p>If <c>trace_procs/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ <p>This callback will be called whenever a tracepoint with trace flag
+ <seealso marker="erlang#trace-3"><c>garbage_collection</c></seealso>
+ is triggered.</p>
+ <p>If <c>enabled_garbage_collection/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
@@ -267,57 +222,36 @@
</func>
<func>
- <name>Module:trace_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
- <fsummary>Check if a trace event should be generated.</fsummary>
- <type>
- <v>TraceTag = <seealso marker="#type-trace_tag_ports">trace_tag()</seealso></v>
- <v>TracerState = term()</v>
- <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>FirstTraceTerm = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
- </type>
- <desc>
- <p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_ports/3">Module:enabled_ports/3</seealso>
- callback returned <c>trace</c>.</p>
- <p>If <c>trace_ports/5</c> is not defined <c>trace/5</c> will be called instead.</p>
- </desc>
- </func>
-
- <func>
- <name>Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag_procs()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
<v>Result = trace | discard | remove</v>
</type>
<desc>
<p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>running_procs | running</c></seealso>
+ <seealso marker="erlang#trace-3"><c>procs</c></seealso>
is triggered.</p>
- <p>If <c>enabled_running_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>If <c>enabled_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:trace_running_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <name>Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_receive">trace_tag_receive()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>FirstTraceTerm = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
+ <v>Result = trace | discard | remove</v>
</type>
<desc>
- <p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_running_procs/3">Module:enabled_running_procs/3</seealso>
- callback returned <c>trace</c>.</p>
- <p>If <c>trace_running_procs/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ <p>This callback will be called whenever a tracepoint with trace flag
+ <seealso marker="erlang#trace-3"><c>'receive'</c></seealso>
+ is triggered.</p>
+ <p>If <c>enabled_receive/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
@@ -339,42 +273,84 @@
</func>
<func>
- <name>Module:trace_running_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <name>Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_running_ports">trace_tag_running_ports()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>FirstTraceTerm = term()</v>
- <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
+ <v>Result = trace | discard | remove</v>
</type>
<desc>
- <p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_running_ports/3">Module:enabled_running_ports/3</seealso>
- callback returned <c>trace</c>.</p>
- <p>If <c>trace_running_ports/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ <p>This callback will be called whenever a tracepoint with trace flag
+ <seealso marker="erlang#trace-3"><c>running_procs | running</c></seealso>
+ is triggered.</p>
+ <p>If <c>enabled_running_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:enabled_call(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:enabled_send(TraceTag, TracerState, Tracee) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_call">trace_tag_call()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
<v>Result = trace | discard | remove</v>
</type>
<desc>
<p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>call | return_to</c></seealso>
+ <seealso marker="erlang#trace-3"><c>send</c></seealso>
is triggered.</p>
- <p>If <c>enabled_call/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>If <c>enabled_send/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
</desc>
</func>
<func>
+ <name>Module:trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <fsummary>Check if a trace event should be generated.</fsummary>
+ <type>
+ <v>TraceTag = <seealso marker="#type-trace_tag">trace_tag()</seealso></v>
+ <v>TracerState = term()</v>
+ <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
+ <v>FirstTraceTerm = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
+ </type>
+ <desc>
+ <p>This callback will be called when a tracepoint is triggered and
+ the <seealso marker="#Module:enabled/3">Module:enabled/3</seealso>
+ callback returned <c>trace</c>. In it any side effects needed by
+ the tracer should be done. The tracepoint payload is located in
+ the <c>TraceTerm</c>. The content of the TraceTerm depends on which
+ <c>TraceTag</c> has been triggered.
+ The <c>TraceTerm</c> corresponds to the
+ fourth element in the trace tuples described in
+ <seealso marker="erlang#trace_3_trace_messages">erlang:trace/3</seealso>.
+ If the trace tuple has five elements, the fifth element will be sent as
+ the <c>extra</c> value in the <c>Opts</c> maps.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="trace">Module:trace(seq_trace, TracerState, Label, SeqTraceInfo, Opts) -> Result</name>
+ <fsummary>Check if a sequence trace event should be generated.</fsummary>
+ <type>
+ <v>TracerState = term()</v>
+ <v>Label = term()</v>
+ <v>SeqTraceInfo = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
+ </type>
+ <desc>
+ <p>The <c>TraceTag</c> <c>seq_trace</c> is handled a little bit
+ differently. There is not <c>Tracee</c> for seq_trace, instead the
+ <c>Label</c> associated with the seq_trace event is given.
+ For more info on what <c>Label</c> and <c>SeqTraceInfo</c> can be
+ see the <seealso marker="kernel:seq_trace">seq_trace</seealso> manual.</p>
+ </desc>
+ </func>
+
+ <func>
<name>Module:trace_call(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
@@ -394,55 +370,59 @@
</func>
<func>
- <name>Module:enabled_send(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:trace_garbage_collection(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>Result = trace | discard | remove</v>
+ <v>FirstTraceTerm = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
</type>
<desc>
- <p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>send</c></seealso>
- is triggered.</p>
- <p>If <c>enabled_send/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>This callback will be called when a tracepoint is triggered and
+ the <seealso marker="#Module:enabled_garbage_collection/3">Module:enabled_garbage_collection/3</seealso>
+ callback returned <c>trace</c>.</p>
+ <p>If <c>trace_garbage_collection/5</c> is not defined <c>trace/5</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:trace_send(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <name>Module:trace_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_ports">trace_tag()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
<v>FirstTraceTerm = term()</v>
<v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
- <v>Result = ok</v>
+ <v>Result = ok</v>
</type>
<desc>
<p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_send/3">Module:enabled_send/3</seealso>
+ the <seealso marker="#Module:enabled_ports/3">Module:enabled_ports/3</seealso>
callback returned <c>trace</c>.</p>
- <p>If <c>trace_send/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ <p>If <c>trace_ports/5</c> is not defined <c>trace/5</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:trace_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_receive">trace_tag_receive()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>Result = trace | discard | remove</v>
+ <v>FirstTraceTerm = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
</type>
<desc>
- <p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>'receive'</c></seealso>
- is triggered.</p>
- <p>If <c>enabled_receive/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>This callback will be called when a tracepoint is triggered and
+ the <seealso marker="#Module:enabled_procs/3">Module:enabled_procs/3</seealso>
+ callback returned <c>trace</c>.</p>
+ <p>If <c>trace_procs/5</c> is not defined <c>trace/5</c> will be called instead.</p>
</desc>
</func>
@@ -466,27 +446,48 @@
</func>
<func>
- <name>Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result</name>
+ <name>Module:trace_running_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_running_ports">trace_tag_running_ports()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
- <v>Result = trace | discard | remove</v>
+ <v>FirstTraceTerm = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
</type>
<desc>
- <p>This callback will be called whenever a tracepoint with trace flag
- <seealso marker="erlang#trace-3"><c>garbage_collection</c></seealso>
- is triggered.</p>
- <p>If <c>enabled_garbage_collection/3</c> is not defined <c>enabled/3</c> will be called instead.</p>
+ <p>This callback will be called when a tracepoint is triggered and
+ the <seealso marker="#Module:enabled_running_ports/3">Module:enabled_running_ports/3</seealso>
+ callback returned <c>trace</c>.</p>
+ <p>If <c>trace_running_ports/5</c> is not defined <c>trace/5</c> will be called instead.</p>
</desc>
</func>
<func>
- <name>Module:trace_garbage_collection(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <name>Module:trace_running_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
<fsummary>Check if a trace event should be generated.</fsummary>
<type>
- <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v>
+ <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v>
+ <v>TracerState = term()</v>
+ <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
+ <v>FirstTraceTerm = term()</v>
+ <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v>
+ <v>Result = ok</v>
+ </type>
+ <desc>
+ <p>This callback will be called when a tracepoint is triggered and
+ the <seealso marker="#Module:enabled_running_procs/3">Module:enabled_running_procs/3</seealso>
+ callback returned <c>trace</c>.</p>
+ <p>If <c>trace_running_procs/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:trace_send(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result</name>
+ <fsummary>Check if a trace event should be generated.</fsummary>
+ <type>
+ <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v>
<v>TracerState = term()</v>
<v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v>
<v>FirstTraceTerm = term()</v>
@@ -495,9 +496,9 @@
</type>
<desc>
<p>This callback will be called when a tracepoint is triggered and
- the <seealso marker="#Module:enabled_garbage_collection/3">Module:enabled_garbage_collection/3</seealso>
+ the <seealso marker="#Module:enabled_send/3">Module:enabled_send/3</seealso>
callback returned <c>trace</c>.</p>
- <p>If <c>trace_garbage_collection/5</c> is not defined <c>trace/5</c> will be called instead.</p>
+ <p>If <c>trace_send/5</c> is not defined <c>trace/5</c> will be called instead.</p>
</desc>
</func>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 6289f033b2..cab18ac8b8 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -74,27 +74,33 @@
Supported time unit representations:</p>
<taglist>
<tag><c>PartsPerSecond :: integer() >= 1</c></tag>
- <item><p>Time unit expressed in parts per second. That is,
+ <item>
+ <p>Time unit expressed in parts per second. That is,
the time unit equals <c>1/PartsPerSecond</c> second.</p></item>
<tag><c>seconds</c></tag>
- <item><p>Symbolic representation of the time unit
+ <item>
+ <p>Symbolic representation of the time unit
represented by the integer <c>1</c>.</p></item>
<tag><c>milli_seconds</c></tag>
- <item><p>Symbolic representation of the time unit
+ <item>
+ <p>Symbolic representation of the time unit
represented by the integer <c>1000</c>.</p></item>
<tag><c>micro_seconds</c></tag>
- <item><p>Symbolic representation of the time unit
+ <item>
+ <p>Symbolic representation of the time unit
represented by the integer <c>1000000</c>.</p></item>
<tag><c>nano_seconds</c></tag>
- <item><p>Symbolic representation of the time unit
+ <item>
+ <p>Symbolic representation of the time unit
represented by the integer <c>1000000000</c>.</p></item>
<tag><c>native</c></tag>
- <item><p>Symbolic representation of the native time unit
+ <item>
+ <p>Symbolic representation of the native time unit
used by the Erlang runtime system.</p>
<p>The <c>native</c> time unit is determined at
@@ -131,7 +137,8 @@
</item>
<tag><c>perf_counter</c></tag>
- <item><p>Symbolic representation of the performance counter
+ <item>
+ <p>Symbolic representation of the performance counter
time unit used by the Erlang runtime system.</p>
<p>The <c>perf_counter</c> time unit behaves much in the same way
@@ -471,17 +478,6 @@
</func>
<func>
- <name name="bitstring_to_list" arity="1"/>
- <fsummary>Converts a bitstring to a list.</fsummary>
- <desc>
- <p>Returns a list of integers corresponding to the bytes of
- <c><anno>Bitstring</anno></c>. If the number of bits in the binary
- is not divisible by 8, the last element of the list is a bitstring
- containing the remaining 1-7 bits.</p>
- </desc>
- </func>
-
- <func>
<name name="binary_to_term" arity="1"/>
<fsummary>Decodes an Erlang external term format binary.</fsummary>
<desc>
@@ -547,6 +543,17 @@
</func>
<func>
+ <name name="bitstring_to_list" arity="1"/>
+ <fsummary>Converts a bitstring to a list.</fsummary>
+ <desc>
+ <p>Returns a list of integers corresponding to the bytes of
+ <c><anno>Bitstring</anno></c>. If the number of bits in the binary
+ is not divisible by 8, the last element of the list is a bitstring
+ containing the remaining 1-7 bits.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="bump_reductions" arity="1"/>
<fsummary>Increments the reduction counter.</fsummary>
<desc>
@@ -583,6 +590,16 @@
</func>
<func>
+ <name name="cancel_timer" arity="1"/>
+ <fsummary>Cancels a timer.</fsummary>
+ <desc>
+ <p>Cancels a timer. The same as calling
+ <seealso marker="#cancel_timer/2"><c>erlang:cancel_timer(TimerRef,
+ [])</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="cancel_timer" arity="2"/>
<fsummary>Cancels a timer.</fsummary>
<desc>
@@ -677,15 +694,6 @@
</desc>
</func>
<func>
- <name name="cancel_timer" arity="1"/>
- <fsummary>Cancels a timer.</fsummary>
- <desc>
- <p>Cancels a timer. The same as calling
- <seealso marker="#cancel_timer/2"><c>erlang:cancel_timer(TimerRef,
- [])</c></seealso>.</p>
- </desc>
- </func>
- <func>
<name name="check_old_code" arity="1"/>
<fsummary>Checks if a module has old code.</fsummary>
<desc>
@@ -935,14 +943,16 @@
<p>The following options are available:</p>
<taglist>
<tag><c>{packet_size, integer() >= 0}</c></tag>
- <item><p>Sets the maximum allowed size of the packet body.
+ <item>
+ <p>Sets the maximum allowed size of the packet body.
If the packet header indicates that the length of the
packet is longer than the maximum allowed length, the
packet is considered invalid. Default is 0, which means
no size limit.</p>
</item>
<tag><c>{line_length, integer() >= 0}</c></tag>
- <item><p>For packet type <c>line</c>, lines longer than
+ <item>
+ <p>For packet type <c>line</c>, lines longer than
the indicated length are truncated.</p>
<p>Option <c>line_length</c> also applies to <c>http*</c>
packet types as an alias for option <c>packet_size</c>
@@ -950,7 +960,8 @@
only intended for backward compatibility.</p>
</item>
<tag><c>{line_delimiter, 0 =&lt; byte() =&lt; 255}</c></tag>
- <item><p>For packet type <c>line</c>, sets the delimiting byte.
+ <item>
+ <p>For packet type <c>line</c>, sets the delimiting byte.
Default is the latin1 character <c>$\n</c>.</p>
</item>
</taglist>
@@ -1239,7 +1250,8 @@ b</pre>
<p>The following behavior applies if <c><anno>Reason</anno></c>
is any term, except <c>normal</c> or <c>kill</c>:</p>
<list type="bulleted">
- <item>If <c><anno>Pid</anno></c> is not trapping exits,
+ <item>
+ If <c><anno>Pid</anno></c> is not trapping exits,
<c><anno>Pid</anno></c>
itself exits with exit reason <c><anno>Reason</anno></c>.
</item>
@@ -1964,6 +1976,19 @@ os_prompt% </pre>
</func>
<func>
+ <name name="iolist_size" arity="1"/>
+ <fsummary>Size of an iolist.</fsummary>
+ <desc>
+ <p>Returns an integer that is the size in bytes
+ of the binary that would be the result of
+ <c>iolist_to_binary(<anno>Item</anno>)</c>, for example:</p>
+ <pre>
+> <input>iolist_size([1,2|&lt;&lt;3,4>>]).</input>
+4</pre>
+ </desc>
+ </func>
+
+ <func>
<name name="iolist_to_binary" arity="1"/>
<fsummary>Converts an iolist to a binary.</fsummary>
<desc>
@@ -1982,19 +2007,6 @@ os_prompt% </pre>
</func>
<func>
- <name name="iolist_size" arity="1"/>
- <fsummary>Size of an iolist.</fsummary>
- <desc>
- <p>Returns an integer that is the size in bytes
- of the binary that would be the result of
- <c>iolist_to_binary(<anno>Item</anno>)</c>, for example:</p>
- <pre>
-> <input>iolist_size([1,2|&lt;&lt;3,4>>]).</input>
-4</pre>
- </desc>
- </func>
-
- <func>
<name name="is_alive" arity="0"/>
<fsummary>Checks whether the local node is alive.</fsummary>
<desc>
@@ -3697,6 +3709,52 @@ os_prompt% </pre>
</func>
<func>
+ <name name="port_call" arity="3"/>
+ <fsummary>Performs a synchronous call to a port with term data.</fsummary>
+ <desc>
+ <p>Performs a synchronous call to a port. The meaning of
+ <c><anno>Operation</anno></c> and <c><anno>Data</anno></c>
+ depends on the port, that is,
+ on the port driver. Not all port drivers support this feature.</p>
+ <p><c><anno>Port</anno></c> is a port identifier,
+ referring to a driver.</p>
+ <p><c><anno>Operation</anno></c> is an integer, which is passed on to
+ the driver.</p>
+ <p><c><anno>Data</anno></c> is any Erlang term. This data is converted
+ to binary term format and sent to the port.</p>
+ <p>Returns a term from the driver. The meaning of the returned
+ data also depends on the port driver.</p>
+ <p>Failures:</p>
+ <taglist>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Port</anno></c> is not an identifier of an open port,
+ or the registered name of an open port. If the calling
+ process was previously linked to the closed port,
+ identified by <c><anno>Port</anno></c>, the exit signal
+ from the port is guaranteed to be delivered before this
+ <c>badarg</c> exception occurs.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Operation</anno></c> does not fit in a 32-bit integer.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If the port driver does not support synchronous control
+ operations.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If the port driver so decides for any reason (probably
+ something wrong with <c><anno>Operation</anno></c>
+ or <c><anno>Data</anno></c>).
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
<name name="port_close" arity="1"/>
<fsummary>Closes an open port.</fsummary>
<desc>
@@ -3952,52 +4010,6 @@ os_prompt% </pre>
</func>
<func>
- <name name="port_call" arity="3"/>
- <fsummary>Performs a synchronous call to a port with term data.</fsummary>
- <desc>
- <p>Performs a synchronous call to a port. The meaning of
- <c><anno>Operation</anno></c> and <c><anno>Data</anno></c>
- depends on the port, that is,
- on the port driver. Not all port drivers support this feature.</p>
- <p><c><anno>Port</anno></c> is a port identifier,
- referring to a driver.</p>
- <p><c><anno>Operation</anno></c> is an integer, which is passed on to
- the driver.</p>
- <p><c><anno>Data</anno></c> is any Erlang term. This data is converted
- to binary term format and sent to the port.</p>
- <p>Returns a term from the driver. The meaning of the returned
- data also depends on the port driver.</p>
- <p>Failures:</p>
- <taglist>
- <tag><c>badarg</c></tag>
- <item>
- If <c><anno>Port</anno></c> is not an identifier of an open port,
- or the registered name of an open port. If the calling
- process was previously linked to the closed port,
- identified by <c><anno>Port</anno></c>, the exit signal
- from the port is guaranteed to be delivered before this
- <c>badarg</c> exception occurs.
- </item>
- <tag><c>badarg</c></tag>
- <item>
- If <c><anno>Operation</anno></c> does not fit in a 32-bit integer.
- </item>
- <tag><c>badarg</c></tag>
- <item>
- If the port driver does not support synchronous control
- operations.
- </item>
- <tag><c>badarg</c></tag>
- <item>
- If the port driver so decides for any reason (probably
- something wrong with <c><anno>Operation</anno></c>
- or <c><anno>Data</anno></c>).
- </item>
- </taglist>
- </desc>
- </func>
-
- <func>
<name name="port_info" arity="1"/>
<fsummary>Information about a port.</fsummary>
<desc>
@@ -4454,14 +4466,16 @@ os_prompt% </pre>
are stored. When the flag is:</p>
<taglist>
<tag><c>off_heap</c></tag>
- <item><p>
+ <item>
+ <p>
<em>All</em> messages in the message queue will be stored
outside of the process heap. This implies that <em>no</em>
messages in the message queue will be part of a garbage
collection of the process.
</p></item>
<tag><c>on_heap</c></tag>
- <item><p>
+ <item>
+ <p>
All messages in the message queue will eventually be
placed on heap. They may however temporarily be stored
off heap. This is how messages always have been stored
@@ -5126,6 +5140,15 @@ os_prompt% </pre>
</func>
<func>
+ <name name="read_timer" arity="1"/>
+ <fsummary>Reads the state of a timer.</fsummary>
+ <desc>
+ <p>Read the state of a timer. The same as calling
+ <seealso marker="#read_timer/2"><c>erlang:read_timer(TimerRef,
+ [])</c></seealso>.</p>
+ </desc>
+ </func>
+ <func>
<name name="read_timer" arity="2"/>
<fsummary>Reads the state of a timer.</fsummary>
<desc>
@@ -5191,15 +5214,6 @@ os_prompt% </pre>
<seealso marker="#cancel_timer/2"><c>erlang:cancel_timer/2</c></seealso>.</p>
</desc>
</func>
- <func>
- <name name="read_timer" arity="1"/>
- <fsummary>Reads the state of a timer.</fsummary>
- <desc>
- <p>Read the state of a timer. The same as calling
- <seealso marker="#read_timer/2"><c>erlang:read_timer(TimerRef,
- [])</c></seealso>.</p>
- </desc>
- </func>
<func>
<name name="ref_to_list" arity="1"/>
@@ -5370,6 +5384,15 @@ true</pre>
</func>
<func>
+ <name name="send_after" arity="3"/>
+ <fsummary>Starts a timer.</fsummary>
+ <desc>
+ <p>Starts a timer. The same as calling
+ <seealso marker="#send_after/4"><c>erlang:send_after(<anno>Time</anno>,
+ <anno>Dest</anno>, <anno>Msg</anno>, [])</c></seealso>.</p>
+ </desc>
+ </func>
+ <func>
<name name="send_after" arity="4"/>
<fsummary>Start a timer</fsummary>
<desc>
@@ -5382,15 +5405,6 @@ true</pre>
<seealso marker="#start_timer/4"><c>erlang:start_timer/4</c></seealso>.</p>
</desc>
</func>
- <func>
- <name name="send_after" arity="3"/>
- <fsummary>Starts a timer.</fsummary>
- <desc>
- <p>Starts a timer. The same as calling
- <seealso marker="#send_after/4"><c>erlang:send_after(<anno>Time</anno>,
- <anno>Dest</anno>, <anno>Msg</anno>, [])</c></seealso>.</p>
- </desc>
- </func>
<func>
<name name="send_nosuspend" arity="2"/>
@@ -5892,6 +5906,16 @@ true</pre>
</func>
<func>
+ <name name="start_timer" arity="3"/>
+ <fsummary>Starts a timer.</fsummary>
+ <desc>
+ <p>Starts a timer. The same as calling
+ <seealso marker="#start_timer/4"><c>erlang:start_timer(<anno>Time</anno>,
+ <anno>Dest</anno>, <anno>Msg</anno>, [])</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="start_timer" arity="4"/>
<fsummary>Starts a timer.</fsummary>
<desc>
@@ -5962,16 +5986,6 @@ true</pre>
</func>
<func>
- <name name="start_timer" arity="3"/>
- <fsummary>Starts a timer.</fsummary>
- <desc>
- <p>Starts a timer. The same as calling
- <seealso marker="#start_timer/4"><c>erlang:start_timer(<anno>Time</anno>,
- <anno>Dest</anno>, <anno>Msg</anno>, [])</c></seealso>.</p>
- </desc>
- </func>
-
- <func>
<name name="statistics" arity="1" clause_i="1"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc><marker id="statistics_active_tasks"></marker>
@@ -6368,6 +6382,20 @@ ok
</func>
<func>
+ <name name="suspend_process" arity="1"/>
+ <fsummary>Suspends a process.</fsummary>
+ <desc>
+ <p>Suspends the process identified by
+ <c><anno>Suspendee</anno></c>. The same as calling
+ <seealso marker="#suspend_process/2">erlang:suspend_process(<anno>Suspendee</anno>,
+ [])</seealso>.</p>
+ <warning>
+ <p>This BIF is intended for debugging only.</p>
+ </warning>
+ </desc>
+ </func>
+
+ <func>
<name name="suspend_process" arity="2"/>
<fsummary>Suspends a process.</fsummary>
<desc>
@@ -6469,20 +6497,6 @@ ok
</func>
<func>
- <name name="suspend_process" arity="1"/>
- <fsummary>Suspends a process.</fsummary>
- <desc>
- <p>Suspends the process identified by
- <c><anno>Suspendee</anno></c>. The same as calling
- <seealso marker="#suspend_process/2">erlang:suspend_process(<anno>Suspendee</anno>,
- [])</seealso>.</p>
- <warning>
- <p>This BIF is intended for debugging only.</p>
- </warning>
- </desc>
- </func>
-
- <func>
<name name="system_flag" arity="2" clause_i="1"/>
<fsummary>Sets system flag <c>backtrace_depth</c>.</fsummary>
<desc>
@@ -6750,39 +6764,48 @@ ok
bound and can be any of the following:</p>
<taglist>
<tag><c>unbound</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt u</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>no_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt ns</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>thread_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt ts</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>processor_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt ps</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt s</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>no_node_thread_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt nnts</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>no_node_processor_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt nnps</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>thread_no_node_processor_spread</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt tnnps</seealso> in <c>erl(1)</c>.
</p></item>
<tag><c>default_bind</c></tag>
- <item><p>Same as command-line argument
+ <item>
+ <p>Same as command-line argument
<seealso marker="erts:erl#+sbt">+sbt db</seealso> in <c>erl(1)</c>.
</p></item>
</taglist>
@@ -6877,16 +6900,19 @@ ok
is used, the time offset state is left unchanged.</p>
<p>Returns the old state identifier. That is:</p>
<list>
- <item><p>If <c>preliminary</c> is returned, finalization was
+ <item>
+ <p>If <c>preliminary</c> is returned, finalization was
performed and the time offset is now final.</p></item>
- <item><p>If <c>final</c> is returned, the time offset was
+ <item>
+ <p>If <c>final</c> is returned, the time offset was
already in the final state. This either because another
<c>erlang:system_flag(time_offset, finalize)</c> call, or
because <seealso marker="time_correction#No_Time_Warp_Mode">no
time warp mode</seealso> is used.</p></item>
- <item><p>If <c>volatile</c> is returned, the time offset
+ <item>
+ <p>If <c>volatile</c> is returned, the time offset
cannot be finalized because
<seealso marker="time_correction#Multi_Time_Warp_Mode">multi
time warp mode</seealso> is used.</p></item>
@@ -7468,7 +7494,8 @@ ok
<c>dtrace</c> or <c>systemtap</c>).</p>
</item>
<tag><marker id="system_info_end_time"/><c>end_time</c></tag>
- <item><p>The last <seealso marker="#monotonic_time/0">Erlang monotonic
+ <item>
+ <p>The last <seealso marker="#monotonic_time/0">Erlang monotonic
time</seealso> in <c>native</c>
<seealso marker="#type_time_unit">time unit</seealso> that
can be represented internally in the current Erlang runtime system
@@ -7695,18 +7722,21 @@ ok
introduced in the future:</p>
<taglist>
<tag><c>{function, Function}</c></tag>
- <item><p><c>Function</c> is the name of the function
+ <item>
+ <p><c>Function</c> is the name of the function
used. This tuple always exist if OS monotonic time is
available to the runtime system.</p></item>
<tag><c>{clock_id, ClockId}</c></tag>
- <item><p>This tuple only exist if <c>Function</c>
+ <item>
+ <p>This tuple only exist if <c>Function</c>
can be used with different clocks. <c>ClockId</c>
corresponds to the clock identifier used when calling
<c>Function</c>.</p></item>
<tag><c>{resolution, OsMonotonicTimeResolution}</c></tag>
- <item><p>Highest possible
+ <item>
+ <p>Highest possible
<seealso marker="time_correction#Time_Resolution">resolution</seealso>
of current OS monotonic time source as parts per
second. If no resolution information can be retrieved
@@ -7724,7 +7754,8 @@ ok
<c>OsMonotonicTimeResolution</c>.</p></item>
<tag><c>{extended, Extended}</c></tag>
- <item><p><c>Extended</c> equals <c>yes</c> if
+ <item>
+ <p><c>Extended</c> equals <c>yes</c> if
the range of time values has been extended;
otherwise, <c>Extended</c> equals <c>no</c>. The
range needs to be extended if <c>Function</c>
@@ -7733,14 +7764,16 @@ ok
value.</p></item>
<tag><c>{parallel, Parallel}</c></tag>
- <item><p><c>Parallel</c> equals <c>yes</c> if
+ <item>
+ <p><c>Parallel</c> equals <c>yes</c> if
<c>Function</c> is called in parallel from multiple
threads. If it is not called in parallel, because
calls needs to be serialized, <c>Parallel</c> equals
<c>no</c>.</p></item>
<tag><c>{time, OsMonotonicTime}</c></tag>
- <item><p><c>OsMonotonicTime</c> equals current OS
+ <item>
+ <p><c>OsMonotonicTime</c> equals current OS
monotonic time in <c>native</c>
<seealso marker="#type_time_unit">time unit</seealso>.</p></item>
</taglist>
@@ -7757,17 +7790,20 @@ ok
introduced in the future:</p>
<taglist>
<tag><c>{function, Function}</c></tag>
- <item><p><c>Function</c> is the name of the funcion
- used.</p></item>
-
+ <item>
+ <p><c>Function</c> is the name of the funcion
+ used.</p>
+ </item>
<tag><c>{clock_id, ClockId}</c></tag>
- <item><p>This tuple only exist if <c>Function</c>
+ <item>
+ <p>This tuple only exist if <c>Function</c>
can be used with different clocks. <c>ClockId</c>
corresponds to the clock identifier used when calling
- <c>Function</c>.</p></item>
-
+ <c>Function</c>.</p>
+ </item>
<tag><c>{resolution, OsSystemTimeResolution}</c></tag>
- <item><p>Highest possible
+ <item>
+ <p>Highest possible
<seealso marker="time_correction#Time_Resolution">resolution</seealso>
of current OS system time source as parts per
second. If no resolution information can be retrieved
@@ -7782,19 +7818,22 @@ ok
<seealso marker="time_correction#Time_Precision">precision</seealso>
do align with the resolution. You do,
however, know that the precision is not better than
- <c>OsSystemTimeResolution</c>.</p></item>
-
+ <c>OsSystemTimeResolution</c>.</p>
+ </item>
<tag><c>{parallel, Parallel}</c></tag>
- <item><p><c>Parallel</c> equals <c>yes</c> if
+ <item>
+ <p><c>Parallel</c> equals <c>yes</c> if
<c>Function</c> is called in parallel from multiple
threads. If it is not called in parallel, because
calls needs to be serialized, <c>Parallel</c> equals
- <c>no</c>.</p></item>
-
+ <c>no</c>.</p>
+ </item>
<tag><c>{time, OsSystemTime}</c></tag>
- <item><p><c>OsSystemTime</c> equals current OS
+ <item>
+ <p><c>OsSystemTime</c> equals current OS
system time in <c>native</c>
- <seealso marker="#type_time_unit">time unit</seealso>.</p></item>
+ <seealso marker="#type_time_unit">time unit</seealso>.</p>
+ </item>
</taglist>
</item>
<tag><c>port_parallelism</c></tag>
@@ -7930,7 +7969,8 @@ ok
with SMP support, otherwise <c>false</c> is returned.</p>
</item>
<tag><marker id="system_info_start_time"/><c>start_time</c></tag>
- <item><p>The <seealso marker="#monotonic_time/0">Erlang monotonic
+ <item>
+ <p>The <seealso marker="#monotonic_time/0">Erlang monotonic
time</seealso> in <c>native</c>
<seealso marker="#type_time_unit">time unit</seealso> at the
time when current Erlang runtime system instance started. See also
@@ -7973,14 +8013,16 @@ ok
<p>Returns the state of the time offset:</p>
<taglist>
<tag><c>preliminary</c></tag>
- <item><p>The time offset is preliminary, and will be changed
+ <item>
+ <p>The time offset is preliminary, and will be changed
at a later time when being finalized. The preliminary time offset
is used during the preliminary phase of the
<seealso marker="time_correction#Single_Time_Warp_Mode">single
time warp mode</seealso>.</p></item>
<tag><c>final</c></tag>
- <item><p>The time offset is final. This either because
+ <item>
+ <p>The time offset is final. This either because
<seealso marker="time_correction#No_Time_Warp_Mode">no
time warp mode</seealso> is used, or because the time
offset have been finalized when
@@ -7988,27 +8030,32 @@ ok
time warp mode</seealso> is used.</p></item>
<tag><c>volatile</c></tag>
- <item><p>The time offset is volatile. That is, it can
+ <item>
+ <p>The time offset is volatile. That is, it can
change at any time. This is because
<seealso marker="time_correction#Multi_Time_Warp_Mode">multi
time warp mode</seealso> is used.</p></item>
</taglist>
</item>
<tag><marker id="system_info_time_warp_mode"/><c>time_warp_mode</c></tag>
- <item><p>Returns a value identifying the
+ <item>
+ <p>Returns a value identifying the
<seealso marker="time_correction#Time_Warp_Modes">time warp
mode</seealso> being used:</p>
<taglist>
<tag><c>no_time_warp</c></tag>
- <item><p>The <seealso marker="time_correction#No_Time_Warp_Mode">no
+ <item>
+ <p>The <seealso marker="time_correction#No_Time_Warp_Mode">no
time warp mode</seealso> is used.</p></item>
<tag><c>single_time_warp</c></tag>
- <item><p>The <seealso marker="time_correction#Single_Time_Warp_Mode">single
+ <item>
+ <p>The <seealso marker="time_correction#Single_Time_Warp_Mode">single
time warp mode</seealso> is used.</p></item>
<tag><c>multi_time_warp</c></tag>
- <item><p>The <seealso marker="time_correction#Multi_Time_Warp_Mode">multi
+ <item>
+ <p>The <seealso marker="time_correction#Multi_Time_Warp_Mode">multi
time warp mode</seealso> is used.</p></item>
</taglist>
</item>
@@ -9705,42 +9752,6 @@ timestamp() ->
</func>
<func>
- <name name="universaltime" arity="0"/>
- <fsummary>Current date and time according to Universal Time Coordinated (UTC).</fsummary>
- <desc>
- <p>Returns the current date and time according to Universal
- Time Coordinated (UTC) in the form
- <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if
- supported by the underlying OS.
- Otherwise <c>erlang:universaltime()</c> is equivalent to
- <c>erlang:localtime()</c>.</p>
- <p>Example:</p>
- <pre>
-> <input>erlang:universaltime().</input>
-{{1996,11,6},{14,18,43}}</pre>
- </desc>
- </func>
-
- <func>
- <name name="universaltime_to_localtime" arity="1"/>
- <fsummary>Converts from Universal Time Coordinated (UTC) to local date and time.</fsummary>
- <desc>
- <p>Converts Universal Time Coordinated (UTC) date and time to
- local date and time in the form
- <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if
- supported by the underlying OS.
- Otherwise no conversion is done, and
- <c><anno>Universaltime</anno></c> is returned.</p>
- <p>Example:</p>
- <pre>
-> <input>erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).</input>
-{{1996,11,7},{15,18,43}}</pre>
- <p>Failure: <c>badarg</c> if <c>Universaltime</c> denotes
- an invalid date and time.</p>
- </desc>
- </func>
-
- <func>
<name name="unique_integer" arity="0"/>
<fsummary>Get a unique integer value</fsummary>
<desc>
@@ -9778,14 +9789,16 @@ timestamp() ->
<taglist>
<tag>positive</tag>
- <item><p>Return only positive integers.</p>
+ <item>
+ <p>Return only positive integers.</p>
<p>Note that by passing the <c>positive</c> modifier
you will get heap allocated integers (bignums)
quicker.</p>
</item>
<tag>monotonic</tag>
- <item><p>Return
+ <item>
+ <p>Return
<seealso marker="time_correction#Strictly_Monotonically_Increasing">strictly
monotonically increasing</seealso> integers
corresponding to creation time. That is, the integer
@@ -9834,6 +9847,43 @@ timestamp() ->
</taglist>
</desc>
</func>
+
+ <func>
+ <name name="universaltime" arity="0"/>
+ <fsummary>Current date and time according to Universal Time Coordinated (UTC).</fsummary>
+ <desc>
+ <p>Returns the current date and time according to Universal
+ Time Coordinated (UTC) in the form
+ <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if
+ supported by the underlying OS.
+ Otherwise <c>erlang:universaltime()</c> is equivalent to
+ <c>erlang:localtime()</c>.</p>
+ <p>Example:</p>
+ <pre>
+> <input>erlang:universaltime().</input>
+{{1996,11,6},{14,18,43}}</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="universaltime_to_localtime" arity="1"/>
+ <fsummary>Converts from Universal Time Coordinated (UTC) to local date and time.</fsummary>
+ <desc>
+ <p>Converts Universal Time Coordinated (UTC) date and time to
+ local date and time in the form
+ <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if
+ supported by the underlying OS.
+ Otherwise no conversion is done, and
+ <c><anno>Universaltime</anno></c> is returned.</p>
+ <p>Example:</p>
+ <pre>
+> <input>erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).</input>
+{{1996,11,7},{15,18,43}}</pre>
+ <p>Failure: <c>badarg</c> if <c>Universaltime</c> denotes
+ an invalid date and time.</p>
+ </desc>
+ </func>
+
<func>
<name name="unlink" arity="1"/>
<fsummary>Removes a link to another process or port.</fsummary>
diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml
index 861661043f..a3c94e4a7f 100644
--- a/erts/doc/src/zlib.xml
+++ b/erts/doc/src/zlib.xml
@@ -106,10 +106,36 @@ list_to_binary([Compressed|Last])</pre>
</datatypes>
<funcs>
<func>
- <name name="open" arity="0"/>
- <fsummary>Open a stream and return a stream reference</fsummary>
+ <name name="adler32" arity="2"/>
+ <fsummary>Calculate the adler checksum</fsummary>
<desc>
- <p>Open a zlib stream.</p>
+ <p>Calculate the Adler-32 checksum for <c><anno>Data</anno></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="adler32" arity="3"/>
+ <fsummary>Calculate the adler checksum</fsummary>
+ <desc>
+ <p>Update a running Adler-32 checksum for <c><anno>Data</anno></c>.
+ If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
+ the required initial value for the checksum.</p>
+ <pre>
+Crc = lists:foldl(fun(Data,Crc0) ->
+ zlib:adler32(Z, Crc0, Data),
+ end, zlib:adler32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
+ </desc>
+ </func>
+ <func>
+ <name name="adler32_combine" arity="4"/>
+ <fsummary>Combine two Adler-32 checksums</fsummary>
+ <desc>
+ <p>Combine two Adler-32 checksums into one. For two binaries or iolists,
+ <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
+ <c><anno>Size2</anno></c>, with Adler-32 checksums <c><anno>Adler1</anno></c> and
+ <c><anno>Adler2</anno></c>. <c>adler32_combine/4</c> returns the <c><anno>Adler</anno></c>
+ checksum of <c>[Data1,Data2]</c>, requiring
+ only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>.
+ </p>
</desc>
</func>
<func>
@@ -120,6 +146,108 @@ list_to_binary([Compressed|Last])</pre>
</desc>
</func>
<func>
+ <name name="compress" arity="1"/>
+ <fsummary>Compress data with standard zlib functionality</fsummary>
+ <desc>
+ <p>Compress data (with zlib headers and checksum).</p>
+ </desc>
+ </func>
+ <func>
+ <name name="crc32" arity="1"/>
+ <fsummary>Get current CRC</fsummary>
+ <desc>
+ <p>Get the current calculated CRC checksum.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="crc32" arity="2"/>
+ <fsummary>Calculate CRC</fsummary>
+ <desc>
+ <p>Calculate the CRC checksum for <c><anno>Data</anno></c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="crc32" arity="3"/>
+ <fsummary>Calculate CRC</fsummary>
+ <desc>
+ <p>Update a running CRC checksum for <c><anno>Data</anno></c>.
+ If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
+ the required initial value for the crc.</p>
+ <pre>
+Crc = lists:foldl(fun(Data,Crc0) ->
+ zlib:crc32(Z, Crc0, Data),
+ end, zlib:crc32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
+ </desc>
+ </func>
+ <func>
+ <name name="crc32_combine" arity="4"/>
+ <fsummary>Combine two CRC's</fsummary>
+ <desc>
+ <p>Combine two CRC checksums into one. For two binaries or iolists,
+ <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
+ <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> and
+ <c><anno>CRC2</anno></c>. <c>crc32_combine/4</c> returns the <c><anno>CRC</anno></c>
+ checksum of <c>[Data1,Data2]</c>, requiring
+ only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="deflate" arity="2"/>
+ <fsummary>Compress data</fsummary>
+ <desc>
+ <p>Same as <c>deflate(<anno>Z</anno>, <anno>Data</anno>, none)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="deflate" arity="3"/>
+ <fsummary>Compress data</fsummary>
+ <desc>
+ <p><c>deflate/3</c> compresses as much data as possible, and
+ stops when the input buffer becomes empty. It may introduce
+ some output latency (reading input without producing any
+ output) except when forced to flush.</p>
+ <p>If the parameter <c><anno>Flush</anno></c> is set to <c>sync</c>, all
+ pending output is flushed to the output buffer and the
+ output is aligned on a byte boundary, so that the
+ decompressor can get all input data available so far.
+ Flushing may degrade compression for some compression algorithms and so
+ it should be used only when necessary.</p>
+ <p>If <c><anno>Flush</anno></c> is set to <c>full</c>, all output is flushed as with
+ <c>sync</c>, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using <c>full</c> too often can seriously degrade
+ the compression.</p>
+ <p>If the parameter <c><anno>Flush</anno></c> is set to <c>finish</c>,
+ pending input is processed, pending output is flushed and
+ <c>deflate/3</c> returns. Afterwards the only possible
+ operations on the stream are <c>deflateReset/1</c> or <c>deflateEnd/1</c>.</p>
+ <p><c><anno>Flush</anno></c> can be set to <c>finish</c> immediately after
+ <c>deflateInit</c> if all compression is to be done in one step.</p>
+ <pre>
+
+zlib:deflateInit(Z),
+B1 = zlib:deflate(Z,Data),
+B2 = zlib:deflate(Z,&lt;&lt; &gt;&gt;,finish),
+zlib:deflateEnd(Z),
+list_to_binary([B1,B2])</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="deflateEnd" arity="1"/>
+ <fsummary>End deflate session</fsummary>
+ <desc>
+ <p>End the deflate session and cleans all data used.
+ Note that this function will throw an <c>data_error</c>
+ exception if the last call to
+ <c>deflate/3</c> was not called with <c>Flush</c> set to
+ <c>finish</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="deflateInit" arity="1"/>
<fsummary>Initialize a session for compression</fsummary>
<desc>
@@ -181,44 +309,32 @@ list_to_binary([Compressed|Last])</pre>
</desc>
</func>
<func>
- <name name="deflate" arity="2"/>
- <fsummary>Compress data</fsummary>
+ <name name="deflateParams" arity="3"/>
+ <fsummary>Dynamicly update deflate parameters</fsummary>
<desc>
- <p>Same as <c>deflate(<anno>Z</anno>, <anno>Data</anno>, none)</c>.</p>
+ <p>Dynamically update the compression level and compression
+ strategy. The interpretation of <c><anno>Level</anno></c> and
+ <c><anno>Strategy</anno></c> is as in <c>deflateInit/6</c>. This can be
+ used to switch between compression and straight copy of the
+ input data, or to switch to a different kind of input data
+ requiring a different strategy. If the compression level is
+ changed, the input available so far is compressed with the
+ old level (and may be flushed); the new level will take
+ effect only at the next call of <c>deflate/3</c>.</p>
+ <p>Before the call of <c>deflateParams</c>, the stream state must be set as for
+ a call of <c>deflate/3</c>, since the currently available input may have to
+ be compressed and flushed.</p>
</desc>
</func>
<func>
- <name name="deflate" arity="3"/>
- <fsummary>Compress data</fsummary>
+ <name name="deflateReset" arity="1"/>
+ <fsummary>Reset the deflate session</fsummary>
<desc>
- <p><c>deflate/3</c> compresses as much data as possible, and
- stops when the input buffer becomes empty. It may introduce
- some output latency (reading input without producing any
- output) except when forced to flush.</p>
- <p>If the parameter <c><anno>Flush</anno></c> is set to <c>sync</c>, all
- pending output is flushed to the output buffer and the
- output is aligned on a byte boundary, so that the
- decompressor can get all input data available so far.
- Flushing may degrade compression for some compression algorithms and so
- it should be used only when necessary.</p>
- <p>If <c><anno>Flush</anno></c> is set to <c>full</c>, all output is flushed as with
- <c>sync</c>, and the compression state is reset so that decompression can
- restart from this point if previous compressed data has been damaged or if
- random access is desired. Using <c>full</c> too often can seriously degrade
- the compression.</p>
- <p>If the parameter <c><anno>Flush</anno></c> is set to <c>finish</c>,
- pending input is processed, pending output is flushed and
- <c>deflate/3</c> returns. Afterwards the only possible
- operations on the stream are <c>deflateReset/1</c> or <c>deflateEnd/1</c>.</p>
- <p><c><anno>Flush</anno></c> can be set to <c>finish</c> immediately after
- <c>deflateInit</c> if all compression is to be done in one step.</p>
- <pre>
-
-zlib:deflateInit(Z),
-B1 = zlib:deflate(Z,Data),
-B2 = zlib:deflate(Z,&lt;&lt; &gt;&gt;,finish),
-zlib:deflateEnd(Z),
-list_to_binary([B1,B2])</pre>
+ <p>This function is equivalent to <c>deflateEnd/1</c>
+ followed by <c>deflateInit/[1|2|6]</c>, but does not free
+ and reallocate all the internal compression state. The
+ stream will keep the same compression level and any other
+ attributes.</p>
</desc>
</func>
<func>
@@ -236,66 +352,24 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
- <name name="deflateReset" arity="1"/>
- <fsummary>Reset the deflate session</fsummary>
- <desc>
- <p>This function is equivalent to <c>deflateEnd/1</c>
- followed by <c>deflateInit/[1|2|6]</c>, but does not free
- and reallocate all the internal compression state. The
- stream will keep the same compression level and any other
- attributes.</p>
- </desc>
- </func>
- <func>
- <name name="deflateParams" arity="3"/>
- <fsummary>Dynamicly update deflate parameters</fsummary>
- <desc>
- <p>Dynamically update the compression level and compression
- strategy. The interpretation of <c><anno>Level</anno></c> and
- <c><anno>Strategy</anno></c> is as in <c>deflateInit/6</c>. This can be
- used to switch between compression and straight copy of the
- input data, or to switch to a different kind of input data
- requiring a different strategy. If the compression level is
- changed, the input available so far is compressed with the
- old level (and may be flushed); the new level will take
- effect only at the next call of <c>deflate/3</c>.</p>
- <p>Before the call of <c>deflateParams</c>, the stream state must be set as for
- a call of <c>deflate/3</c>, since the currently available input may have to
- be compressed and flushed.</p>
- </desc>
- </func>
- <func>
- <name name="deflateEnd" arity="1"/>
- <fsummary>End deflate session</fsummary>
+ <name name="getBufSize" arity="1"/>
+ <fsummary>Get buffer size</fsummary>
<desc>
- <p>End the deflate session and cleans all data used.
- Note that this function will throw an <c>data_error</c>
- exception if the last call to
- <c>deflate/3</c> was not called with <c>Flush</c> set to
- <c>finish</c>.</p>
+ <p>Get the size of intermediate buffer.</p>
</desc>
</func>
<func>
- <name name="inflateInit" arity="1"/>
- <fsummary>Initialize a session for decompression</fsummary>
+ <name name="gunzip" arity="1"/>
+ <fsummary>Uncompress data with gz header</fsummary>
<desc>
- <p>Initialize a zlib stream for decompression.</p>
+ <p>Uncompress data (with gz headers and checksum).</p>
</desc>
</func>
<func>
- <name name="inflateInit" arity="2"/>
- <fsummary>Initialize a session for decompression</fsummary>
+ <name name="gzip" arity="1"/>
+ <fsummary>Compress data with gz header</fsummary>
<desc>
- <p>Initialize decompression session on zlib stream.</p>
- <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm
- of the maximum window size (the size of the history buffer).
- It should be in the range 8 through 15.
- The default value is 15 if <c>inflateInit/1</c> is used.
- If a compressed stream with a larger window size is
- given as input, inflate() will throw the <c>data_error</c>
- exception. A negative <c><anno>WindowBits</anno></c> value makes zlib ignore the
- zlib header (and checksum) from the stream. Note that the zlib
- source mentions this only as a undocumented feature.</p>
+ <p>Compress data (with gz headers and checksum).</p>
</desc>
</func>
<func>
@@ -313,6 +387,16 @@ list_to_binary([B1,B2])</pre>
</desc>
</func>
<func>
+ <name name="inflateChunk" arity="1"/>
+ <fsummary>Read next uncompressed chunk</fsummary>
+ <desc>
+ <p>Read next chunk of uncompressed data, initialized by
+ <c>inflateChunk/2</c>.</p>
+ <p>This function should be repeatedly called, while it returns
+ <c>{more, Decompressed}</c>.</p>
+ </desc>
+ </func>
+ <func>
<name name="inflateChunk" arity="2"/>
<fsummary>Decompress data with limited output size</fsummary>
<desc>
@@ -350,13 +434,46 @@ loop(Z, Handler, Uncompressed) ->
</desc>
</func>
<func>
- <name name="inflateChunk" arity="1"/>
- <fsummary>Read next uncompressed chunk</fsummary>
+ <name name="inflateEnd" arity="1"/>
+ <fsummary>End inflate session</fsummary>
<desc>
- <p>Read next chunk of uncompressed data, initialized by
- <c>inflateChunk/2</c>.</p>
- <p>This function should be repeatedly called, while it returns
- <c>{more, Decompressed}</c>.</p>
+ <p>End the inflate session and cleans all data used. Note
+ that this function will throw a <c>data_error</c> exception
+ if no end of stream was found (meaning that not all data
+ has been uncompressed).</p>
+ </desc>
+ </func>
+ <func>
+ <name name="inflateInit" arity="1"/>
+ <fsummary>Initialize a session for decompression</fsummary>
+ <desc>
+ <p>Initialize a zlib stream for decompression.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="inflateInit" arity="2"/>
+ <fsummary>Initialize a session for decompression</fsummary>
+ <desc>
+ <p>Initialize decompression session on zlib stream.</p>
+ <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm
+ of the maximum window size (the size of the history buffer).
+ It should be in the range 8 through 15.
+ The default value is 15 if <c>inflateInit/1</c> is used.
+ If a compressed stream with a larger window size is
+ given as input, inflate() will throw the <c>data_error</c>
+ exception. A negative <c><anno>WindowBits</anno></c> value makes zlib ignore the
+ zlib header (and checksum) from the stream. Note that the zlib
+ source mentions this only as a undocumented feature.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="inflateReset" arity="1"/>
+ <fsummary>>Reset the inflate session</fsummary>
+ <desc>
+ <p>This function is equivalent to <c>inflateEnd/1</c> followed
+ by <c>inflateInit/1</c>, but does not free and reallocate all
+ the internal decompression state. The stream will keep
+ attributes that may have been set by <c>inflateInit/[1|2]</c>.</p>
</desc>
</func>
<func>
@@ -384,23 +501,10 @@ unpack(Z, Compressed, Dict) ->
</desc>
</func>
<func>
- <name name="inflateReset" arity="1"/>
- <fsummary>>Reset the inflate session</fsummary>
- <desc>
- <p>This function is equivalent to <c>inflateEnd/1</c> followed
- by <c>inflateInit/1</c>, but does not free and reallocate all
- the internal decompression state. The stream will keep
- attributes that may have been set by <c>inflateInit/[1|2]</c>.</p>
- </desc>
- </func>
- <func>
- <name name="inflateEnd" arity="1"/>
- <fsummary>End inflate session</fsummary>
+ <name name="open" arity="0"/>
+ <fsummary>Open a stream and return a stream reference</fsummary>
<desc>
- <p>End the inflate session and cleans all data used. Note
- that this function will throw a <c>data_error</c> exception
- if no end of stream was found (meaning that not all data
- has been uncompressed).</p>
+ <p>Open a zlib stream.</p>
</desc>
</func>
<func>
@@ -411,93 +515,6 @@ unpack(Z, Compressed, Dict) ->
</desc>
</func>
<func>
- <name name="getBufSize" arity="1"/>
- <fsummary>Get buffer size</fsummary>
- <desc>
- <p>Get the size of intermediate buffer.</p>
- </desc>
- </func>
- <func>
- <name name="crc32" arity="1"/>
- <fsummary>Get current CRC</fsummary>
- <desc>
- <p>Get the current calculated CRC checksum.</p>
- </desc>
- </func>
- <func>
- <name name="crc32" arity="2"/>
- <fsummary>Calculate CRC</fsummary>
- <desc>
- <p>Calculate the CRC checksum for <c><anno>Data</anno></c>.</p>
- </desc>
- </func>
- <func>
- <name name="crc32" arity="3"/>
- <fsummary>Calculate CRC</fsummary>
- <desc>
- <p>Update a running CRC checksum for <c><anno>Data</anno></c>.
- If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
- the required initial value for the crc.</p>
- <pre>
-Crc = lists:foldl(fun(Data,Crc0) ->
- zlib:crc32(Z, Crc0, Data),
- end, zlib:crc32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
- </desc>
- </func>
- <func>
- <name name="crc32_combine" arity="4"/>
- <fsummary>Combine two CRC's</fsummary>
- <desc>
- <p>Combine two CRC checksums into one. For two binaries or iolists,
- <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
- <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> and
- <c><anno>CRC2</anno></c>. <c>crc32_combine/4</c> returns the <c><anno>CRC</anno></c>
- checksum of <c>[Data1,Data2]</c>, requiring
- only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>.
- </p>
- </desc>
- </func>
- <func>
- <name name="adler32" arity="2"/>
- <fsummary>Calculate the adler checksum</fsummary>
- <desc>
- <p>Calculate the Adler-32 checksum for <c><anno>Data</anno></c>.</p>
- </desc>
- </func>
- <func>
- <name name="adler32" arity="3"/>
- <fsummary>Calculate the adler checksum</fsummary>
- <desc>
- <p>Update a running Adler-32 checksum for <c><anno>Data</anno></c>.
- If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns
- the required initial value for the checksum.</p>
- <pre>
-Crc = lists:foldl(fun(Data,Crc0) ->
- zlib:adler32(Z, Crc0, Data),
- end, zlib:adler32(Z,&lt;&lt; &gt;&gt;), Datas)</pre>
- </desc>
- </func>
- <func>
- <name name="adler32_combine" arity="4"/>
- <fsummary>Combine two Adler-32 checksums</fsummary>
- <desc>
- <p>Combine two Adler-32 checksums into one. For two binaries or iolists,
- <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and
- <c><anno>Size2</anno></c>, with Adler-32 checksums <c><anno>Adler1</anno></c> and
- <c><anno>Adler2</anno></c>. <c>adler32_combine/4</c> returns the <c><anno>Adler</anno></c>
- checksum of <c>[Data1,Data2]</c>, requiring
- only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>.
- </p>
- </desc>
- </func>
- <func>
- <name name="compress" arity="1"/>
- <fsummary>Compress data with standard zlib functionality</fsummary>
- <desc>
- <p>Compress data (with zlib headers and checksum).</p>
- </desc>
- </func>
- <func>
<name name="uncompress" arity="1"/>
<fsummary>Uncompress data with standard zlib functionality</fsummary>
<desc>
@@ -505,13 +522,6 @@ Crc = lists:foldl(fun(Data,Crc0) ->
</desc>
</func>
<func>
- <name name="zip" arity="1"/>
- <fsummary>Compress data without the zlib headers</fsummary>
- <desc>
- <p>Compress data (without zlib headers and checksum).</p>
- </desc>
- </func>
- <func>
<name name="unzip" arity="1"/>
<fsummary>Uncompress data without the zlib headers</fsummary>
<desc>
@@ -519,17 +529,10 @@ Crc = lists:foldl(fun(Data,Crc0) ->
</desc>
</func>
<func>
- <name name="gzip" arity="1"/>
- <fsummary>Compress data with gz header</fsummary>
- <desc>
- <p>Compress data (with gz headers and checksum).</p>
- </desc>
- </func>
- <func>
- <name name="gunzip" arity="1"/>
- <fsummary>Uncompress data with gz header</fsummary>
+ <name name="zip" arity="1"/>
+ <fsummary>Compress data without the zlib headers</fsummary>
<desc>
- <p>Uncompress data (with gz headers and checksum).</p>
+ <p>Compress data (without zlib headers and checksum).</p>
</desc>
</func>
</funcs>