diff options
Diffstat (limited to 'erts/doc/src/erl_nif.xml')
-rw-r--r-- | erts/doc/src/erl_nif.xml | 4283 |
1 files changed, 2580 insertions, 1703 deletions
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index f3921f1922..2b627281fe 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -33,43 +33,52 @@ <file>erl_nif.xml</file> </header> <lib>erl_nif</lib> - <libsummary>API functions for an Erlang NIF library</libsummary> + <libsummary>API functions for an Erlang NIF library.</libsummary> <description> <p>A NIF library contains native implementation of some functions - of an Erlang module. The native implemented functions (NIFs) are - called like any other functions without any difference to the - caller. Each NIF must also have an implementation in Erlang that - will be invoked if the function is called before the NIF library - has been successfully loaded. A typical such stub implementation - is to throw an exception. But it can also be used as a fallback - implementation if the NIF library is not implemented for some - architecture.</p> - <marker id="WARNING"/> - <warning><p><em>Use this functionality with extreme care!</em></p> + of an Erlang module. The native implemented functions (NIFs) are + called like any other functions without any difference to the + caller. Each NIF must have an implementation in Erlang that + is invoked if the function is called before the NIF library + is successfully loaded. A typical such stub implementation + is to throw an exception. But it can also be used as a fallback + implementation if the NIF library is not implemented for some + architecture.</p> + + <warning> + <marker id="WARNING"/> + <p><em>Use this functionality with extreme care.</em></p> <p>A native function is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can <em>not</em> provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the native function doesn't behave well, the whole - VM will misbehave.</p> - <list> - <item><p>A native function that crash will crash the whole VM.</p></item> - <item><p>An erroneously implemented native function might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the native function.</p></item> - <item><p>A native function that do <seealso marker="#lengthy_work">lengthy - work</seealso> before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.</p></item> + native code of the VM. Execution is not made in a safe environment. + The VM <em>cannot</em> provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the native function does not behave well, the whole + VM will misbehave.</p> + <list type="bulleted"> + <item> + <p>A native function that crash will crash the whole VM.</p> + </item> + <item> + <p>An erroneously implemented native function can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the native function.</p> + </item> + <item> + <p>A native function doing <seealso marker="#lengthy_work">lengthy + work</seealso> before returning degrades responsiveness of the VM, + and can cause miscellaneous strange behaviors. Such strange + behaviors include, but are not limited to, extreme memory usage, + and bad load balancing between schedulers. Strange behaviors that + can occur because of lengthy work can also vary between Erlang/OTP + releases.</p> + </item> </list> - </warning> + </warning> - <p>A minimal example of a NIF library can look like this:</p> - <p/> - <code type="none"> + <p>A minimal example of a NIF library can look as follows:</p> + + <code type="none"> /* niftest.c */ #include "erl_nif.h" @@ -83,13 +92,11 @@ static ErlNifFunc nif_funcs[] = {"hello", 0, hello} }; -ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL) -</code> +ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)</code> + + <p>The Erlang module can look as follows:</p> - <p>and the Erlang module would have to look something like - this:</p> - <p/> - <code type="none"> + <code type="none"> -module(niftest). -export([init/0, hello/0]). @@ -98,11 +105,11 @@ init() -> erlang:load_nif("./niftest", 0). hello() -> - "NIF library not loaded". -</code> - <p>and compile and test something like this (on Linux):</p> - <p/> - <code type="none"> + "NIF library not loaded".</code> + + <p>Compile and test can look as follows (on Linux):</p> + + <code type="none"> $> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/ $> erl @@ -113,1353 +120,1948 @@ $> erl 3> niftest:init(). ok 4> niftest:hello(). -"Hello world!" -</code> - - <p>A better solution for a real module is to take advantage of - the new directive <seealso - marker="doc/reference_manual:code_loading#on_load">on_load</seealso> to automatically - load the NIF library when the module is loaded.</p> - <note><p>A NIF does not have to be exported, it can be local to the module. - Note however that unused local stub functions will be optimized - away by the compiler causing loading of the NIF library to fail.</p> +"Hello world!"</code> + + <p>A better solution for a real module is to take advantage of the new + directive <c>on load</c> (see section + <seealso marker="doc/reference_manual:code_loading#on_load">Running a + Function When a Module is Loaded</seealso> in the Erlang Reference + Manual) to load the NIF library automatically when the module is + loaded.</p> + + <note> + <p>A NIF does not have to be exported, it can be local to the module. + However, 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 - to). The new code version can however choose to load the exact - same NIF library as the old code if it wants to. Sharing the same - dynamic library will mean that static data defined by the library - will be shared as well. To avoid unintentionally shared static - data, each Erlang module code can keep its own private data. This - private data can be set when the NIF library is loaded and - then retrieved by calling <seealso marker="#enif_priv_data">enif_priv_data</seealso>.</p> - <p>There is no way to explicitly unload a NIF library. A library will be - automatically unloaded when the module code that it belongs to is purged - by the code server.</p> + <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 need to load its own NIF library (or maybe choose not + to). The new code version can, however, choose to load the + same NIF library as the old code if it wants to. Sharing the + dynamic library means that static data defined by the library + is shared as well. To avoid unintentionally shared static + data, each Erlang module code can keep its own private data. This + private data can be set when the NIF library is loaded and + then retrieved by calling <seealso marker="#enif_priv_data"> + <c>enif_priv_data</c></seealso>.</p> + + <p>A NIF library cannot be loaded explicitly. A library is + automatically unloaded when the module code that it belongs to is purged + by the code server.</p> </description> + <section> - <title>FUNCTIONALITY</title> - <p>All functions that a NIF library needs to do with Erlang are - performed through the NIF API functions. There are functions + <title>Functionality</title> + <p>All functions that a NIF library needs to do with Erlang are + performed through the NIF API functions. Functions exist for the following functionality:</p> + <taglist> <tag>Read and write Erlang terms</tag> - <item><p>Any Erlang terms can be passed to a NIF as function arguments and - be returned as function return values. The terms are of C-type - <seealso marker="#ERL_NIF_TERM">ERL_NIF_TERM</seealso> - and can only be read or written using API functions. Most functions to read - the content of a term are prefixed <c>enif_get_</c> and usually return - true (or false) if the term was of the expected type (or not). - The functions to write terms are all prefixed <c>enif_make_</c> and usually - return the created <c>ERL_NIF_TERM</c>. There are also some functions - to query terms, like <c>enif_is_atom</c>, <c>enif_is_identical</c> and - <c>enif_compare</c>.</p> - <p>All terms of type <c>ERL_NIF_TERM</c> belong to an environment of type - <seealso marker="#ErlNifEnv">ErlNifEnv</seealso>. The lifetime of a term is - controlled by the lifetime of its environment object. All API functions that read - or write terms has the environment, that the term belongs to, as the first - function argument.</p></item> + <item> + <p>Any Erlang terms can be passed to a NIF as function arguments and + be returned as function return values. The terms are of C-type + <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso> and can + only be read or written using API functions. Most functions to read + the content of a term are prefixed <c>enif_get_</c> and usually return + <c>true</c> (or <c>false</c>) if the term is of the expected type (or + not). The functions to write terms are all prefixed <c>enif_make_</c> + and usually + return the created <c>ERL_NIF_TERM</c>. There are also some functions + to query terms, like <c>enif_is_atom</c>, <c>enif_is_identical</c>, + and <c>enif_compare</c>.</p> + <p>All terms of type <c>ERL_NIF_TERM</c> belong to an environment of + type <seealso marker="#ErlNifEnv"><c>ErlNifEnv</c></seealso>. The + lifetime of a term is controlled by the lifetime of its environment + object. All API functions that read or write terms has the + environment that the term belongs to as the first function + argument.</p> + </item> <tag>Binaries</tag> - <item><p>Terms of type binary are accessed with the help of the struct type - <seealso marker="#ErlNifBinary">ErlNifBinary</seealso> - that contains a pointer (<c>data</c>) to the raw binary data and the length - (<c>size</c>) of the data in bytes. Both <c>data</c> and <c>size</c> are - read-only and should only be written using calls to API functions. - Instances of <c>ErlNifBinary</c> are however always allocated by the user - (usually as local variables).</p> - <p>The raw data pointed to by <c>data</c> is only mutable after a call to - <seealso marker="#enif_alloc_binary">enif_alloc_binary</seealso> or - <seealso marker="#enif_realloc_binary">enif_realloc_binary</seealso>. - All other functions that operates on a binary will leave the data as read-only. - A mutable binary must in the end either be freed with - <seealso marker="#enif_release_binary">enif_release_binary</seealso> - or made read-only by transferring it to an Erlang term with - <seealso marker="#enif_make_binary">enif_make_binary</seealso>. - But it does not have to happen in the same NIF call. Read-only binaries - do not have to be released.</p> - <p><seealso marker="#enif_make_new_binary">enif_make_new_binary</seealso> - can be used as a shortcut to allocate and return a binary in the same NIF call.</p> - <p>Binaries are sequences of whole bytes. Bitstrings with an arbitrary - bit length have no support yet.</p> - </item> + <item> + <p>Terms of type binary are accessed with the help of struct type + <seealso marker="#ErlNifBinary"><c>ErlNifBinary</c></seealso>, + which contains a pointer (<c>data</c>) to the raw binary data and the + length (<c>size</c>) of the data in bytes. Both <c>data</c> and + <c>size</c> are read-only and are only to be written using calls to + API functions. Instances of <c>ErlNifBinary</c> are, however, always + allocated by the user (usually as local variables).</p> + <p>The raw data pointed to by <c>data</c> is only mutable after a call + to <seealso marker="#enif_alloc_binary"> + <c>enif_alloc_binary</c></seealso> or + <seealso marker="#enif_realloc_binary"> + <c>enif_realloc_binary</c></seealso>. All other functions that + operate on a binary leave the data as read-only. + A mutable binary must in the end either be freed with + <seealso marker="#enif_release_binary"> + <c>enif_release_binary</c></seealso> + or made read-only by transferring it to an Erlang term with + <seealso marker="#enif_make_binary"><c>enif_make_binary</c></seealso>. + However, it does not have to occur in the same NIF call. Read-only + binaries do not have to be released.</p> + <p><seealso marker="#enif_make_new_binary"> + <c>enif_make_new_binary</c></seealso> can be used as a shortcut to + allocate and return a binary in the same NIF call.</p> + <p>Binaries are sequences of whole bytes. Bitstrings with an arbitrary + bit length have no support yet.</p> + </item> <tag>Resource objects</tag> - <item><p>The use of resource objects is a safe way to return pointers to - native data structures from a NIF. A resource object is - just a block of memory allocated with - <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - A handle ("safe pointer") to this memory block can then be returned to Erlang by the use of - <seealso marker="#enif_make_resource">enif_make_resource</seealso>. - The term returned by <c>enif_make_resource</c> - is totally opaque in nature. It can be stored and passed between processes - on the same node, but the only real end usage is to pass it back as an argument to a NIF. - The NIF can then call <seealso marker="#enif_get_resource">enif_get_resource</seealso> - and get back a pointer to the memory block that is guaranteed to still be - valid. A resource object will not be deallocated until the last handle term - has been garbage collected by the VM and the resource has been - released with <seealso marker="#enif_release_resource">enif_release_resource</seealso> - (not necessarily in that order).</p> - <p>All resource objects are created as instances of some <em>resource type</em>. - This makes resources from different modules to be distinguishable. - A resource type is created by calling - <seealso marker="#enif_open_resource_type">enif_open_resource_type</seealso> - when a library is loaded. Objects of that resource type can then later be allocated - and <c>enif_get_resource</c> verifies that the resource is of the expected type. - A resource type can have a user supplied destructor function that is - automatically called when resources of that type are released (by either - the garbage collector or <c>enif_release_resource</c>). Resource types - are uniquely identified by a supplied name string and the name of the - implementing module.</p> - <marker id="enif_resource_example"/><p>Here is a template example of how to create and return a resource object.</p> - <p/> - <code type="none"> - ERL_NIF_TERM term; - MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); - - /* initialize struct ... */ - - term = enif_make_resource(env, obj); - - if (keep_a_reference_of_our_own) { - /* store 'obj' in static variable, private data or other resource object */ - } - else { - enif_release_resource(obj); - /* resource now only owned by "Erlang" */ - } - return term; - </code> - <p>Note that once <c>enif_make_resource</c> creates the term to - return to Erlang, the code can choose to either keep its own - native pointer to the allocated struct and release it later, or - release it immediately and rely solely on the garbage collector - to eventually deallocate the resource object when it collects - the term.</p> - <p>Another usage of resource objects is to create binary terms with - user defined memory management. - <seealso marker="#enif_make_resource_binary">enif_make_resource_binary</seealso> - will create a binary term that is connected to a resource object. The - destructor of the resource will be called when the binary is garbage - collected, at which time the binary data can be released. An example of - this can be a binary term consisting of data from a <c>mmap</c>'ed file. - The destructor can then do <c>munmap</c> to release the memory - region.</p> - <p>Resource types support upgrade in runtime by allowing a loaded NIF - library to takeover an already existing resource type and thereby - "inherit" all existing objects of that type. The destructor of the new - library will thereafter be called for the inherited objects and the - library with the old destructor function can be safely unloaded. Existing - resource objects, of a module that is upgraded, must either be deleted - or taken over by the new NIF library. The unloading of a library will be - postponed as long as there exist resource objects with a destructor - function in the library. - </p> + <item> + <p>The use of resource objects is a safe way to return pointers to + native data structures from a NIF. A resource object is + only a block of memory allocated with + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. + A handle ("safe pointer") to this memory block can then be returned + to Erlang by the use of + <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso>. + The term returned by <c>enif_make_resource</c> is opaque in nature. + It can be stored and passed between processes on the same node, but + the only real end usage is to pass it back as an argument to a NIF. + The NIF can then call <seealso marker="#enif_get_resource"> + <c>enif_get_resource</c></seealso> and get back a pointer to the + memory block, which is guaranteed to still be valid. A resource + object is not deallocated until the last handle term + is garbage collected by the VM and the resource is released with + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso> + (not necessarily in that order).</p> + <p>All resource objects are created as instances of some <em>resource + type</em>. This makes resources from different modules to be + distinguishable. A resource type is created by calling + <seealso marker="#enif_open_resource_type"> + <c>enif_open_resource_type</c></seealso> when a library is loaded. + Objects of that resource type can then later be allocated and + <c>enif_get_resource</c> verifies that the resource is of the + expected type. A resource type can have a user-supplied destructor + function, which is automatically called when resources of that type + are released (by either the garbage collector or + <c>enif_release_resource</c>). Resource types are uniquely identified + by a supplied name string and the name of the implementing module.</p> + <marker id="enif_resource_example"/> + <p>The following is a template example of how to create and return a + resource object.</p> + <code type="none"> +ERL_NIF_TERM term; +MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); + +/* initialize struct ... */ + +term = enif_make_resource(env, obj); + +if (keep_a_reference_of_our_own) { + /* store 'obj' in static variable, private data or other resource object */ +} +else { + enif_release_resource(obj); + /* resource now only owned by "Erlang" */ +} +return term;</code> + <p>Notice that once <c>enif_make_resource</c> creates the term to + return to Erlang, the code can choose to either keep its own + native pointer to the allocated struct and release it later, or + release it immediately and rely only on the garbage collector + to deallocate the resource object eventually when it collects + the term.</p> + <p>Another use of resource objects is to create binary terms with + user-defined memory management. + <seealso marker="#enif_make_resource_binary"> + <c>enif_make_resource_binary</c></seealso> + creates a binary term that is connected to a resource object. The + destructor of the resource is called when the binary is garbage + collected, at which time the binary data can be released. An example + of this can be a binary term consisting of data from a <c>mmap</c>'ed + file. The destructor can then do <c>munmap</c> to release the memory + region.</p> + <p>Resource types support upgrade in runtime by allowing a loaded NIF + library to take over an already existing resource type and by that + "inherit" all existing objects of that type. The destructor of the + new library is thereafter called for the inherited objects and the + library with the old destructor function can be safely unloaded. + Existing resource objects, of a module that is upgraded, must either + be deleted or taken over by the new NIF library. The unloading of a + library is postponed as long as there exist resource objects with a + destructor function in the library.</p> </item> <tag>Threads and concurrency</tag> - <item><p>A NIF is thread-safe without any explicit synchronization as - long as it acts as a pure function and only reads the supplied - arguments. As soon as you write towards a shared state either through - static variables or <seealso marker="#enif_priv_data">enif_priv_data</seealso> - you need to supply your own explicit synchronization. This includes terms - in process independent environments that are shared between threads. - Resource objects will also require synchronization if you treat them as - mutable.</p> - <p>The library initialization callbacks <c>load</c>, <c>reload</c> and - <c>upgrade</c> are all thread-safe even for shared state data.</p> + <item> + <p>A NIF is thread-safe without any explicit synchronization as + long as it acts as a pure function and only reads the supplied + arguments. When you write to a shared state either through + static variables or <seealso marker="#enif_priv_data"> + <c>enif_priv_data</c></seealso>, you need to supply your own explicit + synchronization. This includes terms in process-independent + environments that are shared between threads. Resource objects also + require synchronization if you treat them as mutable.</p> + <p>The library initialization callbacks <c>load</c>, <c>reload</c>, and + <c>upgrade</c> are all thread-safe even for shared state data.</p> </item> - <tag><marker id="version_management"/>Version Management</tag> - <item><p> - When a NIF library is built, information about NIF API version - is compiled into the library. When a NIF library is loaded the - runtime system verifies that the library is of a compatible version. - <c>erl_nif.h</c> defines <c>ERL_NIF_MAJOR_VERSION</c>, and - <c>ERL_NIF_MINOR_VERSION</c>. <c>ERL_NIF_MAJOR_VERSION</c> will be - incremented when NIF library incompatible changes are made to the - Erlang runtime system. Normally it will suffice to recompile the NIF - library when the <c>ERL_NIF_MAJOR_VERSION</c> has changed, but it - could, under rare circumstances, mean that NIF libraries have to - be slightly modified. If so, this will of course be documented. - <c>ERL_NIF_MINOR_VERSION</c> will be incremented when - new features are added. The runtime system uses the minor version - to determine what features to use. - </p><p> - The runtime system will normally refuse to load a NIF library if - the major versions differ, or if the major versions are equal and - the minor version used by the NIF library is greater than the one - used by the runtime system. Old NIF libraries with lower major - versions will however be allowed after a bump of the major version - during a transition period of two major releases. Such old NIF - libraries might however fail if deprecated features are used. - </p></item> - + <item> + <p>When a NIF library is built, information about the NIF API version + is compiled into the library. When a NIF library is loaded, the + runtime system verifies that the library is of a compatible version. + <c>erl_nif.h</c> defines the following:</p> + <taglist> + <tag><c>ERL_NIF_MAJOR_VERSION</c></tag> + <item> + <p>Incremented when NIF library incompatible changes are made to the + Erlang runtime system. Normally it suffices to recompile the NIF + library when the <c>ERL_NIF_MAJOR_VERSION</c> has changed, but it + can, under rare circumstances, mean that NIF libraries must be + slightly modified. If so, this will of course be documented.</p> + </item> + <tag><c>ERL_NIF_MINOR_VERSION</c></tag> + <item> + <p>Incremented when new features are added. The runtime system uses + the minor version to determine what features to use.</p> + </item> + </taglist> + <p>The runtime system normally refuses to load a NIF library if + the major versions differ, or if the major versions are equal and + the minor version used by the NIF library is greater than the one + used by the runtime system. Old NIF libraries with lower major + versions are, however, allowed after a bump of the major version + during a transition period of two major releases. Such old NIF + libraries can however fail if deprecated features are used.</p> + </item> <tag><marker id="time_measurement"/>Time Measurement</tag> - <item><p>Support for time measurement in NIF libraries:</p> - <list> - <item><seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso></item> - <item><seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso></item> - <item><seealso marker="#enif_monotonic_time"><c>enif_monotonic_time()</c></seealso></item> - <item><seealso marker="#enif_time_offset"><c>enif_time_offset()</c></seealso></item> - <item><seealso marker="#enif_convert_time_unit"><c>enif_convert_time_unit()</c></seealso></item> + <item> + <p>Support for time measurement in NIF libraries:</p> + <list type="bulleted"> + <item><seealso marker="#ErlNifTime"> + <c>ErlNifTime</c></seealso></item> + <item><seealso marker="#ErlNifTimeUnit"> + <c>ErlNifTimeUnit</c></seealso></item> + <item><seealso marker="#enif_monotonic_time"> + <c>enif_monotonic_time()</c></seealso></item> + <item><seealso marker="#enif_time_offset"> + <c>enif_time_offset()</c></seealso></item> + <item><seealso marker="#enif_convert_time_unit"> + <c>enif_convert_time_unit()</c></seealso></item> </list> </item> - <tag><marker id="lengthy_work"/>Long-running NIFs</tag> - - <item><p> - As mentioned in the <seealso marker="#WARNING">warning</seealso> text at - the beginning of this document it is of <em>vital importance</em> that a - native function return relatively quickly. It is hard to give an exact - maximum amount of time that a native function is allowed to work, but as a - rule of thumb a well-behaving native function should return to its caller - before a millisecond has passed. This can be achieved using different - approaches. If you have full control over the code to execute in the - native function, the best approach is to divide the work into multiple - chunks of work and call the native function multiple times. In some - cases this might however not always be possible, e.g. when calling - third-party libraries.</p> - - <p>The - <seealso marker="#enif_consume_timeslice">enif_consume_timeslice()</seealso> - function can be used to inform the runtime system about the length of the - NIF call. It should typically always be used unless the NIF executes very - quickly.</p> - - <p>If the NIF call is too lengthy one needs to handle this in one of the - following ways in order to avoid degraded responsiveness, scheduler load - balancing problems, and other strange behaviors:</p> - - <taglist> - <tag>Yielding NIF</tag> - <item> - <p> - If the functionality of a long-running NIF can be split so that - its work can be achieved through a series of shorter NIF calls, - the application can either make that series of NIF calls from the - Erlang level, or it can call a NIF that first performs a chunk of - the work, then invokes the - <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso> - function to schedule another NIF call to perform the next chunk. - The final call scheduled in this manner can then return the - overall result. Breaking up a long-running function in - this manner enables the VM to regain control between calls to the - NIFs. - </p> - <p> - This approach is always preferred over the other alternatives - described below. This both from a performance perspective and - a system characteristics perspective. - </p> - </item> - - <tag>Threaded NIF</tag> - <item> - <p> - This is accomplished by dispatching the work to another thread - managed by the NIF library, return from the NIF, and wait for the - result. The thread can send the result back to the Erlang - process using <seealso marker="#enif_send">enif_send</seealso>. - Information about thread primitives can be found below. - </p> - </item> - - <tag><marker id="dirty_nifs"/>Dirty NIF</tag> - <item> - - <note> - <p> - <em>The dirty NIF functionality described here - is experimental</em>. Dirty NIF support is available only when - the emulator is configured with dirty schedulers enabled. This - feature is currently disabled by default. The Erlang runtime - without SMP support do not support dirty schedulers even when - the dirty scheduler support has been enabled. To check at - runtime for the presence of dirty scheduler threads, code can - use the - <seealso marker="#enif_system_info"><c>enif_system_info()</c></seealso> - API function. - </p> - </note> - - <p> - A NIF that cannot be split and cannot execute in a millisecond or - less is called a "dirty NIF" because it performs work that the - ordinary schedulers of the Erlang runtime system cannot handle cleanly. - Applications that make use of such functions must indicate to the - runtime that the functions are dirty so they can be handled - specially. This is handled by executing dirty jobs on a separate + <item> + <p>As mentioned in the <seealso marker="#WARNING">warning</seealso> text + at the beginning of this manual page, it is of <em>vital + importance</em> that a native function returns relatively fast. It is + difficult to give an exact maximum amount of time that a native + function is allowed to work, but usually a well-behaving native + function is to return to its caller within 1 millisecond. This can be + achieved using different approaches. If you have full control over the + code to execute in the native function, the best approach is to + divide the work into multiple chunks of work and call the native + function multiple times. This is, however, not always possible, for + example when calling third-party libraries.</p> + <p>The <seealso marker="#enif_consume_timeslice"> + <c>enif_consume_timeslice()</c></seealso> function can be used to + inform the runtime system about the length of the NIF call. + It is typically always to be used unless the NIF executes very + fast.</p> + <p>If the NIF call is too lengthy, this must be handled in one of + the following ways to avoid degraded responsiveness, scheduler load + balancing problems, and other strange behaviors:</p> + <taglist> + <tag>Yielding NIF</tag> + <item> + <p>If the functionality of a long-running NIF can be split so that + its work can be achieved through a series of shorter NIF calls, + the application has two options:</p> + <list type="bulleted"> + <item> + <p>Make that series of NIF calls from the Erlang level.</p> + </item> + <item> + <p>Call a NIF that first performs a chunk of the work, then + invokes the <seealso marker="#enif_schedule_nif"> + <c>enif_schedule_nif</c></seealso> function to schedule + another NIF call to perform the next chunk. The final call + scheduled in this manner can then return the overall + result.</p> + </item> + </list> + <p>Breaking up a long-running function in this manner enables the + VM to regain control between calls to the NIFs.</p> + <p>This approach is always preferred over the other alternatives + described below. This both from a performance perspective and + a system characteristics perspective.</p> + </item> + <tag>Threaded NIF</tag> + <item> + <p>This is accomplished by dispatching the work to another thread + managed by the NIF library, return from the NIF, and wait for + the result. The thread can send the result back to the Erlang + process using <seealso marker="#enif_send"> + <c>enif_send</c></seealso>. + Information about thread primitives is provided below.</p> + </item> + <tag><marker id="dirty_nifs"/>Dirty NIF</tag> + <item> + <note> + <p><em>The dirty NIF functionality described here + is experimental</em>. Dirty NIF support is available only when + the emulator is configured with dirty schedulers enabled. This + feature is disabled by default. The Erlang runtime + without SMP support does not support dirty schedulers even when + the dirty scheduler support is enabled. To check at runtime for + the presence of dirty scheduler threads, code can use the + <seealso marker="#enif_system_info"> + <c>enif_system_info()</c></seealso> API function.</p> + </note> + <p>A NIF that cannot be split and cannot execute in a millisecond + or less is called a "dirty NIF", as it performs work that the + ordinary schedulers of the Erlang runtime system cannot handle cleanly. + Applications that make use of such functions must indicate to the + runtime that the functions are dirty so they can be handled + specially. This is handled by executing dirty jobs on a separate set of schedulers called dirty schedulers. A dirty NIF executing on a dirty scheduler does not have the same duration restriction as a normal NIF. - </p> + </p> - <p> - It is important to classify the dirty job correct. An I/O bound + <p> + It is important to classify the dirty job correct. An I/O bound job should be classified as such, and a CPU bound job should be classified as such. If you should classify CPU bound jobs 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> - To schedule a dirty NIF for execution, the appropriate - <c>flags</c> value can be set for the NIF in its - <seealso marker="#ErlNifFunc"><c>ErlNifFunc</c></seealso> - entry, or the application can call - <seealso marker="#enif_schedule_nif"><c>enif_schedule_nif</c></seealso>, - passing to it a pointer to the dirty NIF to be executed and - indicating with the <c>flags</c> argument whether it expects the - operation to be CPU-bound or I/O-bound. A job that alternates - between I/O bound and CPU bound can be reclassified and - rescheduled using <c>enif_schedule_nif</c> so that it executes on - the correct type of dirty scheduler at all times. For more - information see the documentation of the <c>erl</c> command line - arguments <seealso marker="erl#+SDcpu"><c>+SDcpu</c></seealso>, - and <seealso marker="erl#+SDio"><c>+SDio</c></seealso>. - </p> - - <p> - While a process is executing a dirty NIF some operations that - communicate with it may take a very long time to complete. - Suspend, or garbage collection of a process executing a dirty - NIF cannot be done until the dirty NIF has returned, so other - processes waiting for such operations to complete might have to - wait for a very long time. Blocking multi scheduling, i.e., - calling - <seealso marker="erlang#system_flag_multi_scheduling"><c>erlang:system_flag(multi_scheduling, - block)</c></seealso>, might also take a very long time to - complete. This since all ongoing dirty operations on all - 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 - dirty NIF. For example, retrieving information about it via - <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 - dirty NIF. All Erlang resources such as its registered name, - its ETS tables, etc will be released. All links and monitors - will be triggered. The actual execution of the NIF will - however <em>not</em> be stopped. The NIF can safely continue - execution, allocate heap memory, etc, but it is of course better - to stop executing as soon as possible. The NIF can check - whether current process is alive or not using - <seealso marker="#enif_is_current_process_alive"><c>enif_is_current_process_alive</c></seealso>. - Communication using - <seealso marker="#enif_send"><c>enif_send</c></seealso>, - and <seealso marker="#enif_port_command"><c>enif_port_command</c></seealso> - will also be dropped when the sending process is not alive. - Deallocation of certain internal resources such as process - 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> - <p> - Since purging of a module currently might need to garbage - collect a process in order to determine if it has - references to the module, a process executing a dirty - NIF might delay purging for a very long time. Delaying - a purge operation implies delaying <em>all</em> code - loading operations which might cause severe problems for - the system as a whole. - </p> - </item> - </list> - - </item> - </taglist> + </p> + <p> + To schedule a dirty NIF for execution, the application has two options:</p> + <list type="bulleted"> + <item> + <p>Set the appropriate flags value for the dirty NIF in its + <seealso marker="#ErlNifFunc"> <c>ErlNifFunc</c></seealso> + entry.</p> + </item> + <item> + <p>Call <seealso marker="#enif_schedule_nif"> + <c>enif_schedule_nif</c></seealso>, pass to it a pointer + to the dirty NIF to be executed, and indicate with argument + <c>flags</c> whether it expects the operation to be CPU-bound + or I/O-bound.</p> + </item> + </list> + <p>A job that alternates between I/O bound and CPU bound can be + reclassified and rescheduled using <c>enif_schedule_nif</c> so + that it executes on the correct type of dirty scheduler at all + times. For more information see the documentation of the + <c>erl(1)</c> command line arguments + <seealso marker="erl#+SDcpu"><c>+SDcpu</c></seealso>, + and <seealso marker="erl#+SDio"><c>+SDio</c></seealso>.</p> + <p>While a process executes a dirty NIF, some operations that + communicate with it can take a very long time to complete. + Suspend or garbage collection of a process executing a dirty + NIF cannot be done until the dirty NIF has returned. Thus, other + processes waiting for such operations to complete might + have to wait for a very long time. Blocking multi-scheduling, that + is, calling <seealso marker="erlang#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, block)</c></seealso>, can + also take a very long time to complete. This becaue all ongoing + dirty operations on all dirty schedulers must complete before + the block operation can complete.</p> + <p>Many operations communicating with a process executing a + dirty NIF can, however, complete while it executes the + dirty NIF. For example, retrieving information about it through + <seealso marker="erlang:process_info/1"> + <c>erlang:process_info</c></seealso>, setting its group leader, + register/unregister its name, and so on.</p> + <p>Termination of a process executing a dirty NIF can only be + completed up to a certain point while it executes the dirty NIF. + All Erlang resources, such as its registered name and its <c>ets</c> + tables, are released. All links and monitors are triggered. The + execution of the NIF is, however, <em>not</em> stopped. The NIF + can safely continue execution, allocate heap memory, and so on, + but it is of course better to stop executing as soon as possible. + The NIF can check whether a current process is alive using + <seealso marker="#enif_is_current_process_alive"> + <c>enif_is_current_process_alive</c></seealso>. Communication + using <seealso marker="#enif_send"><c>enif_send</c></seealso> and + <seealso marker="#enif_port_command"> + <c>enif_port_command</c></seealso> is also dropped when the + sending process is not alive. Deallocation of certain internal + resources, such as process heap and process control block, is + delayed until the dirty NIF has completed.</p> + <p>Known issue that are planned to be fixed:</p> + <list type="bulleted"> + <item> + <p>As purging of a module might need to garbage + collect a process to determine if it has + references to the module, a process executing a dirty + NIF can delay purging for a very long time. Delaying + a purge operation implies delaying <em>all</em> code + loading operations, which can cause severe problems for + the system as a whole.</p> + </item> + </list> + </item> + </taglist> </item> </taglist> </section> + <section> - <title>INITIALIZATION</title> + <title>Initialization</title> <taglist> - <tag><marker id="ERL_NIF_INIT"/>ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)</tag> - <item><p>This is the magic macro to initialize a NIF library. It - should be evaluated in global file scope.</p> - <p><c>MODULE</c> is the name of the Erlang module as an - identifier without string quotations. It will be stringified by - the macro.</p> - <p><c>funcs</c> is a static array of function descriptors for - all the implemented NIFs in this library.</p> - <p><c>load</c>, <c>reload</c>, <c>upgrade</c> and <c>unload</c> - are pointers to functions. One of <c>load</c>, <c>reload</c> or - <c>upgrade</c> will be called to initialize the library. - <c>unload</c> is called to release the library. They are all - described individually below.</p> - <p>If compiling a nif for static inclusion via --enable-static-nifs you - have to define STATIC_ERLANG_NIF before the ERL_NIF_INIT declaration.</p> + <tag><marker id="ERL_NIF_INIT"/><c>ERL_NIF_INIT(MODULE, + ErlNifFunc funcs[], load, reload, upgrade, unload)</c></tag> + <item> + <p>This is the magic macro to initialize a NIF library. It + is to be evaluated in global file scope.</p> + <p><c>MODULE</c> is the name of the Erlang module as an + identifier without string quotations. It is stringified by + the macro.</p> + <p><c>funcs</c> is a static array of function descriptors for + all the implemented NIFs in this library.</p> + <p><c>load</c>, <c>reload</c>, <c>upgrade</c> and <c>unload</c> + are pointers to functions. One of <c>load</c>, <c>reload</c>, or + <c>upgrade</c> is called to initialize the library. + <c>unload</c> is called to release the library. All are + described individually below.</p> + <p>If compiling a NIF for static inclusion through + <c>--enable-static-nifs</c>, you must define <c>STATIC_ERLANG_NIF</c> + before the <c>ERL_NIF_INIT</c> declaration.</p> </item> - - <tag><marker id="load"/>int (*load)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag> - <item><p><c>load</c> is called when the NIF library is loaded - and there is no previously loaded library for this module.</p> + <tag><marker id="load"/><c>int (*load)(ErlNifEnv* env, void** priv_data, + ERL_NIF_TERM load_info)</c></tag> + <item> + <p><c>load</c> is called when the NIF library is loaded + and no previously loaded library exists for this module.</p> <p><c>*priv_data</c> can be set to point to some private data - that the library needs in order to keep a state between NIF - calls. <c>enif_priv_data</c> will return this pointer. - <c>*priv_data</c> will be initialized to NULL when <c>load</c> is - called.</p> + that the library needs to keep a state between NIF + calls. <c>enif_priv_data</c> returns this pointer. + <c>*priv_data</c> is initialized to <c>NULL</c> when <c>load</c> is + called.</p> <p><c>load_info</c> is the second argument to <seealso - marker="erlang#load_nif-2">erlang:load_nif/2</seealso>.</p> - <p>The library will fail to load if <c>load</c> returns - anything other than 0. <c>load</c> can be NULL in case no - initialization is needed.</p> - </item> - - <tag><marker id="upgrade"/>int (*upgrade)(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</tag> - <item><p><c>upgrade</c> is called when the NIF library is loaded - and there is old code of this module with a loaded NIF library.</p> - <p>Works the same as <c>load</c>. The only difference is that - <c>*old_priv_data</c> already contains the value set by the - last call to <c>load</c> or <c>reload</c> for the old module - code. <c>*priv_data</c> will be initialized to NULL when <c>upgrade</c> - is called. It is allowed to write to both *priv_data and *old_priv_data.</p> - <p>The library will fail to load if <c>upgrade</c> returns - anything other than 0 or if <c>upgrade</c> is NULL.</p> + marker="erlang#load_nif-2"><c>erlang:load_nif/2</c></seealso>.</p> + <p>The library fails to load if <c>load</c> returns + anything other than <c>0</c>. <c>load</c> can be <c>NULL</c> if + initialization is not needed.</p> </item> - - <tag><marker id="unload"/>void (*unload)(ErlNifEnv* env, void* priv_data)</tag> - <item><p><c>unload</c> is called when the module code that - the NIF library belongs to is purged as old. New code - of the same module may or may not exist. Note that <c>unload</c> is not - called for a replaced library as a consequence of <c>reload</c>.</p> + <tag><marker id="upgrade"/><c>int (*upgrade)(ErlNifEnv* env, void** + priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</c></tag> + <item> + <p><c>upgrade</c> is called when the NIF library is loaded + and there is old code of this module with a loaded NIF library.</p> + <p>Works as <c>load</c>, except that <c>*old_priv_data</c> already + contains the value set by the last call to <c>load</c> or + <c>reload</c> for the old module code. <c>*priv_data</c> is + initialized to <c>NULL</c> when <c>upgrade</c> is called. It is + allowed to write to both <c>*priv_data</c> and + <c>*old_priv_data.</c></p> + <p>The library fails to load if <c>upgrade</c> returns + anything other than <c>0</c> or if <c>upgrade</c> is <c>NULL</c>.</p> </item> - - <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag> - - <item> - <note><p>The reload mechanism is <em>deprecated</em>. It was only intended - as a development feature. Do not use it as an upgrade method for - live production systems. It might be removed in future releases. Be sure - to pass <c>reload</c> as <c>NULL</c> to <seealso marker="#ERL_NIF_INIT">ERL_NIF_INIT</seealso> - to disable it when not used.</p> - </note> - <p><c>reload</c> is called when the NIF library is loaded - and there is already a previously loaded library for this - module code.</p> - <p>Works the same as <c>load</c>. The only difference is that - <c>*priv_data</c> already contains the value set by the - previous call to <c>load</c> or <c>reload</c>.</p> - <p>The library will fail to load if <c>reload</c> returns - anything other than 0 or if <c>reload</c> is NULL.</p> + <tag><marker id="unload"/><c>void (*unload)(ErlNifEnv* env, void* + priv_data)</c></tag> + <item> + <p><c>unload</c> is called when the module code that + the NIF library belongs to is purged as old. New code of the same + module may or may not exist. Notice that <c>unload</c> is not + called for a replaced library as a consequence of <c>reload</c>.</p> + </item> + <tag><marker id="reload"/><c>int (*reload)(ErlNifEnv* env, void** + priv_data, ERL_NIF_TERM load_info)</c></tag> + <item> + <note> + <p><em>The reload mechanism is deprecated.</em> It was only intended + as a development feature. Do not use it as an upgrade method for + live production systems. It can be removed in future releases. + Ensure to pass <c>reload</c> as <c>NULL</c> to + <seealso marker="#ERL_NIF_INIT"><c>ERL_NIF_INIT</c></seealso> + to disable it when not used.</p> + </note> + <p><c>reload</c> is called when the NIF library is loaded and a + previously loaded library already exists for this module code.</p> + <p>Works as <c>load</c>, except that + <c>*priv_data</c> already contains the value set by the + previous call to <c>load</c> or <c>reload</c>.</p> + <p>The library fails to load if <c>reload</c> returns + anything other than <c>0</c> or if <c>reload</c> is <c>NULL</c>.</p> </item> - </taglist> </section> <section> - <title>DATA TYPES</title> - + <title>Data Types</title> <taglist> - <tag><marker id="ERL_NIF_TERM"/>ERL_NIF_TERM</tag> - <item> + <tag><marker id="ERL_NIF_TERM"/><c>ERL_NIF_TERM</c></tag> + <item> <p>Variables of type <c>ERL_NIF_TERM</c> can refer to any Erlang term. - This is an opaque type and values of it can only by used either as - arguments to API functions or as return values from NIFs. All - <c>ERL_NIF_TERM</c>'s belong to an environment - (<seealso marker="#ErlNifEnv">ErlNifEnv</seealso>). A term can not be - destructed individually, it is valid until its environment is destructed.</p> + This is an opaque type and values of it can only by used either as + arguments to API functions or as return values from NIFs. All + <c>ERL_NIF_TERM</c>s belong to an environment + (<seealso marker="#ErlNifEnv"><c>ErlNifEnv</c></seealso>). + A term cannot be destructed individually, it is valid until its + environment is destructed.</p> </item> - <tag><marker id="ErlNifEnv"/>ErlNifEnv</tag> + <tag><marker id="ErlNifEnv"/><c>ErlNifEnv</c></tag> <item> - <p><c>ErlNifEnv</c> represents an environment that can host Erlang terms. - All terms in an environment are valid as long as the environment is valid. - <c>ErlNifEnv</c> is an opaque type and pointers to it can only be passed - on to API functions. There are two types of environments; process - bound and process independent.</p> - <p>A <em>process bound environment</em> is passed as the first argument to all NIFs. - All function arguments passed to a NIF will belong to that environment. - The return value from a NIF must also be a term belonging to the same - environment. - In addition a process bound environment contains transient information - about the calling Erlang process. The environment is only valid in the - thread where it was supplied as argument until the NIF returns. It is - thus useless and dangerous to store pointers to process bound - environments between NIF calls. </p> - <p>A <em>process independent environment</em> is created by calling - <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>. It can be - used to store terms between NIF calls and to send terms with - <seealso marker="#enif_send">enif_send</seealso>. A process - independent environment with all its terms is valid until you explicitly - invalidates it with <seealso marker="#enif_free_env">enif_free_env</seealso> - or <c>enif_send</c>.</p> + <p><c>ErlNifEnv</c> represents an environment that can host Erlang + terms. All terms in an environment are valid as long as the + environment is valid. <c>ErlNifEnv</c> is an opaque type; pointers to + it can only be passed on to API functions. Two types of environments + exist:</p> + <taglist> + <tag>Process-bound environment</tag> + <item> + <p>Passed as the first argument to all NIFs. All function arguments + passed to a NIF belong to that environment. The return value from + a NIF must also be a term belonging to the same environment.</p> + <p>A process-bound environment contains transient information + about the calling Erlang process. The environment is only valid + in the thread where it was supplied as argument until the NIF + returns. It is thus useless and dangerous to store pointers to + process-bound environments between NIF calls.</p> + </item> + <tag>Process-independent environment</tag> + <item> + <p>Created by calling <seealso marker="#enif_alloc_env"> + <c>enif_alloc_env</c></seealso>. This environment can be + used to store terms between NIF calls and to send terms with + <seealso marker="#enif_send"><c>enif_send</c></seealso>. A + process-independent environment with all its terms is valid until + you explicitly invalidate it with + <seealso marker="#enif_free_env"><c>enif_free_env</c></seealso> + or <c>enif_send</c>.</p> + </item> + </taglist> <p>All contained terms of a list/tuple/map must belong to the same - environment as the list/tuple/map itself. Terms can be copied between - environments with - <seealso marker="#enif_make_copy">enif_make_copy</seealso>.</p> + environment as the list/tuple/map itself. Terms can be copied between + environments with + <seealso marker="#enif_make_copy"><c>enif_make_copy</c></seealso>.</p> </item> - <tag><marker id="ErlNifFunc"/>ErlNifFunc</tag> - <item> - <p/> - <code type="none"> + <tag><marker id="ErlNifFunc"/><c>ErlNifFunc</c></tag> + <item> + <code type="none"> typedef struct { const char* name; unsigned arity; ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); unsigned flags; -} ErlNifFunc; -</code> - <p>Describes a NIF by its name, arity and implementation. - <c>fptr</c> is a pointer to the function that implements the - NIF. The argument <c>argv</c> of a NIF will contain the - function arguments passed to the NIF and <c>argc</c> is the - length of the array, i.e. the function arity. <c>argv[N-1]</c> - will thus denote the Nth argument to the NIF. Note that the - <c>argc</c> argument allows for the same C function to - implement several Erlang functions with different arity (but - same name probably). For a regular NIF, <c>flags</c> is 0 (and - so its value can be omitted for statically initialized <c>ErlNifFunc</c> - instances), or it can be used to indicate that the NIF is a <seealso - marker="#dirty_nifs">dirty NIF</seealso> that should be executed - on a dirty scheduler thread (<em>note that the dirty NIF functionality - described here is experimental</em> and that you have to enable - support for dirty schedulers when building OTP in order to try the - functionality out). If the dirty NIF is expected to be - CPU-bound, its <c>flags</c> field should be set to - <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c>, or for I/O-bound jobs, - <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> - <note><p>If one of the - <c>ERL_NIF_DIRTY_JOB_*_BOUND</c> flags is set, and the runtime - system has no support for dirty schedulers, the runtime system - will refuse to load the NIF library.</p></note> +} ErlNifFunc;</code> + <p>Describes a NIF by its name, arity, and implementation.</p> + <taglist> + <tag><c>fptr</c></tag> + <item> + <p>A pointer to the function that implements the NIF.</p> + </item> + <tag><c>argv</c></tag> + <item> + <p>Contains the function arguments passed to the NIF.</p> + </item> + <tag><c>argc</c></tag> + <item> + <p>The array length, that is, the function arity. <c>argv[N-1]</c> + thus denotes the Nth argument to the NIF. Notice that the argument + <c>argc</c> allows for the same C function to implement several + Erlang functions with different arity (but probably with the same + name).</p> + </item> + <tag><c>flags</c></tag> + <item> + <p>Is <c>0</c> for a regular NIF (and so its value can be omitted + for statically initialized <c>ErlNifFunc</c> instances).</p> + <p><c>flags</c> can be used to indicate that the NIF is a + <seealso marker="#dirty_nifs">dirty NIF</seealso> that is to be + executed on a dirty scheduler thread.</p> + <p><em>The dirty NIF functionality described here is + experimental.</em> You have to enable support for dirty + schedulers when building OTP to try out the functionality.</p> + <p>If the dirty NIF is expected to be CPU-bound, its <c>flags</c> + field is to be set to <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> or + <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> + <note> + <p>If one of the <c>ERL_NIF_DIRTY_JOB_*_BOUND</c> flags is set, + and the runtime system has no support for dirty schedulers, + the runtime system refuses to load the NIF library.</p> + </note> + </item> + </taglist> </item> - <tag><marker id="ErlNifBinary"/>ErlNifBinary</tag> - <item> - <p/> - <code type="none"> + <tag><marker id="ErlNifBinary"/><c>ErlNifBinary</c></tag> + <item> + <code type="none"> typedef struct { unsigned size; unsigned char* data; -} ErlNifBinary; -</code> +} ErlNifBinary;</code> <p><c>ErlNifBinary</c> contains transient information about an inspected binary term. <c>data</c> is a pointer to a buffer of <c>size</c> bytes with the raw content of the binary.</p> - <p>Note that <c>ErlNifBinary</c> is a semi-opaque type and you are + <p>Notice that <c>ErlNifBinary</c> is a semi-opaque type and you are only allowed to read fields <c>size</c> and <c>data</c>.</p> </item> - - <tag><marker id="ErlNifBinaryToTerm"/>ErlNifBinaryToTerm</tag> + <tag><marker id="ErlNifBinaryToTerm"/><c>ErlNifBinaryToTerm</c></tag> <item> - <p>An enumeration of the options that can be given to - <seealso marker="#enif_binary_to_term">enif_binary_to_term</seealso>. - For default behavior, use the value <c>0</c>.</p> - <taglist> - <tag><c>ERL_NIF_BIN2TERM_SAFE</c></tag> - <item><p>Use this option when receiving data from untrusted sources.</p></item> - </taglist> + <p>An enumeration of the options that can be specified to + <seealso marker="#enif_binary_to_term"> + <c>enif_binary_to_term</c></seealso>. + For default behavior, use value <c>0</c>.</p> + <p>When receiving data from untrusted sources, use option + <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> </item> - - <tag><marker id="ErlNifPid"/>ErlNifPid</tag> - <item> - <p><c>ErlNifPid</c> is a process identifier (pid). In contrast to - pid terms (instances of <c>ERL_NIF_TERM</c>), <c>ErlNifPid</c>'s are self - contained and not bound to any - <seealso marker="#ErlNifEnv">environment</seealso>. <c>ErlNifPid</c> - is an opaque type.</p> - </item> - <tag><marker id="ErlNifPort"/>ErlNifPort</tag> - <item> - <p><c>ErlNifPort</c> is a port identifier. In contrast to - port id terms (instances of <c>ERL_NIF_TERM</c>), <c>ErlNifPort</c>'s are self - contained and not bound to any - <seealso marker="#ErlNifEnv">environment</seealso>. <c>ErlNifPort</c> - is an opaque type.</p> - </item> - - <tag><marker id="ErlNifResourceType"/>ErlNifResourceType</tag> - <item> - <p>Each instance of <c>ErlNifResourceType</c> represent a class of - memory managed resource objects that can be garbage collected. + <tag><marker id="ErlNifPid"/><c>ErlNifPid</c></tag> + <item> + <p>A process identifier (pid). In contrast to pid terms (instances of + <c>ERL_NIF_TERM</c>), <c>ErlNifPid</c>s are self-contained and not + bound to any <seealso marker="#ErlNifEnv">environment</seealso>. + <c>ErlNifPid</c> is an opaque type.</p> + </item> + <tag><marker id="ErlNifPort"/><c>ErlNifPort</c></tag> + <item> + <p>A port identifier. In contrast to port ID terms (instances of + <c>ERL_NIF_TERM</c>), <c>ErlNifPort</c>s are self-contained and not + bound to any <seealso marker="#ErlNifEnv">environment</seealso>. + <c>ErlNifPort</c> is an opaque type.</p> + </item> + <tag><marker id="ErlNifResourceType"/><c>ErlNifResourceType</c></tag> + <item> + <p>Each instance of <c>ErlNifResourceType</c> represents a class of + memory-managed resource objects that can be garbage collected. Each resource type has a unique name and a destructor function that is called when objects of its type are released.</p> - </item> - <tag><marker id="ErlNifResourceDtor"/>ErlNifResourceDtor</tag> - <item> - <p/> - <code type="none"> -typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); -</code> - <p>The function prototype of a resource destructor function.</p> - </item> - <tag><marker id="ErlNifCharEncoding"/>ErlNifCharEncoding</tag> - <item> - <p/> - <code type="none"> + </item> + <tag><marker id="ErlNifResourceDtor"/><c>ErlNifResourceDtor</c></tag> + <item> + <code type="none"> +typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj);</code> + <p>The function prototype of a resource destructor function.</p> + </item> + <tag><marker id="ErlNifCharEncoding"/><c>ErlNifCharEncoding</c></tag> + <item> + <code type="none"> typedef enum { ERL_NIF_LATIN1 -}ErlNifCharEncoding; -</code> - <p>The character encoding used in strings and atoms. The only - supported encoding is currently <c>ERL_NIF_LATIN1</c> for - iso-latin-1 (8-bit ascii).</p> - </item> - <tag><marker id="ErlNifSysInfo"/>ErlNifSysInfo</tag> - <item> - <p>Used by <seealso marker="#enif_system_info">enif_system_info</seealso> - to return information about the runtime system. Contains currently - the exact same content as <seealso marker="erl_driver#ErlDrvSysInfo">ErlDrvSysInfo</seealso>.</p> - </item> - <tag><marker id="ErlNifSInt64"/>ErlNifSInt64</tag> - <item><p>A native signed 64-bit integer type.</p></item> - <tag><marker id="ErlNifUInt64"/>ErlNifUInt64</tag> - <item><p>A native unsigned 64-bit integer type.</p></item> - - <tag><marker id="ErlNifTime"/>ErlNifTime</tag> +}ErlNifCharEncoding;</code> + <p>The character encoding used in strings and atoms. The only + supported encoding is <c>ERL_NIF_LATIN1</c> for + ISO Latin-1 (8-bit ASCII).</p> + </item> + <tag><marker id="ErlNifSysInfo"/><c>ErlNifSysInfo</c></tag> + <item> + <p>Used by <seealso marker="#enif_system_info"> + <c>enif_system_info</c></seealso> to return information about the + runtime system. Contains the same content as + <seealso marker="erl_driver#ErlDrvSysInfo"> + <c>ErlDrvSysInfo</c></seealso>.</p> + </item> + <tag><marker id="ErlNifSInt64"/><c>ErlNifSInt64</c></tag> + <item> + <p>A native signed 64-bit integer type.</p> + </item> + <tag><marker id="ErlNifUInt64"/><c>ErlNifUInt64</c></tag> + <item> + <p>A native unsigned 64-bit integer type.</p> + </item> + <tag><marker id="ErlNifTime"/><c>ErlNifTime</c></tag> <item> <p>A signed 64-bit integer type for representation of time.</p> </item> - <tag><marker id="ErlNifTimeUnit"/>ErlNifTimeUnit</tag> + <tag><marker id="ErlNifTimeUnit"/><c>ErlNifTimeUnit</c></tag> <item> <p>An enumeration of time units supported by the NIF API:</p> - <taglist> - <tag><c>ERL_NIF_SEC</c></tag> - <item><p>Seconds</p></item> - <tag><c>ERL_NIF_MSEC</c></tag> - <item><p>Milliseconds</p></item> - <tag><c>ERL_NIF_USEC</c></tag> - <item><p>Microseconds</p></item> - <tag><c>ERL_NIF_NSEC</c></tag> - <item><p>Nanoseconds</p></item> - </taglist> + <taglist> + <tag><c>ERL_NIF_SEC</c></tag> + <item>Seconds</item> + <tag><c>ERL_NIF_MSEC</c></tag> + <item>Milliseconds</item> + <tag><c>ERL_NIF_USEC</c></tag> + <item>Microseconds</item> + <tag><c>ERL_NIF_NSEC</c></tag> + <item>Nanoseconds</item> + </taglist> </item> - - <tag><marker id="ErlNifUniqueInteger"/>ErlNifUniqueInteger</tag> + <tag><marker id="ErlNifUniqueInteger"/><c>ErlNifUniqueInteger</c></tag> <item> <p>An enumeration of the properties that can be requested from - <seealso marker="#enif_make_unique_integer">enif_unique_integer</seealso>. - For default properties, use the value <c>0</c>.</p> + <seealso marker="#enif_make_unique_integer"> + <c>enif_unique_integer</c></seealso>. + For default properties, use value <c>0</c>.</p> <taglist> - <tag><c>ERL_NIF_UNIQUE_POSITIVE</c></tag> - <item><p>Return only positive integers</p></item> - <tag><c>ERL_NIF_UNIQUE_MONOTONIC</c></tag> - <item><p>Return only - <seealso marker="time_correction#Strictly_Monotonically_Increasing">strictly - monotonically increasing</seealso> integer corresponding to creation time</p></item> - </taglist> + <tag><c>ERL_NIF_UNIQUE_POSITIVE</c></tag> + <item> + <p>Return only positive integers.</p> + </item> + <tag><c>ERL_NIF_UNIQUE_MONOTONIC</c></tag> + <item> + <p>Return only <seealso + marker="time_correction#Strictly_Monotonically_Increasing"> + strictly monotonically increasing</seealso> integer corresponding + to creation time.</p> + </item> + </taglist> </item> - </taglist> </section> <funcs> - <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> - <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 - refer to the allocated binary. The binary must either be released by - <seealso marker="#enif_release_binary">enif_release_binary</seealso> - or ownership transferred to an Erlang term with - <seealso marker="#enif_make_binary">enif_make_binary</seealso>. - An allocated (and owned) <c>ErlNifBinary</c> can be kept between NIF - calls.</p> - <p>Return true on success or false if allocation failed.</p> - </desc> - </func> - <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 - later be copied to a process environment with - <seealso marker="#enif_make_copy">enif_make_copy</seealso> - or be sent to a process as a message with <seealso marker="#enif_send">enif_send</seealso>.</p> - <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> - <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> - <fsummary>Create a term from the external format</fsummary> - <desc> - <p>Create a term that is the result of decoding the binary data - at <c>data</c>, which must be encoded according to the Erlang external term format. - No more than <c>size</c> bytes are read from <c>data</c>. Argument <c>opts</c> - correspond to the second argument to <seealso marker="erlang#binary_to_term-2"> - <c>erlang:binary_to_term/2</c></seealso>, and must be either <c>0</c> or - <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> - <p>On success, store the resulting term at <c>*term</c> and return - the actual number of bytes read. Return zero if decoding fails or if <c>opts</c> - is invalid.</p> - <p>See also: - <seealso marker="#ErlNifBinaryToTerm"><c>ErlNifBinaryToTerm</c></seealso>, - <seealso marker="erlang#binary_to_term-2"><c>erlang:binary_to_term/2</c></seealso> and - <seealso marker="#enif_term_to_binary"><c>enif_term_to_binary</c></seealso>. - </p> - </desc> + <func> + <name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name> + <fsummary>Allocate dynamic memory.</fsummary> + <desc> + <p>Allocates memory of <c>size</c> bytes.</p> + <p>Returns <c>NULL</c> if the allocation fails.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_alloc_binary(size_t size, ErlNifBinary* bin)</nametext> + </name> + <fsummary>Create a new binary.</fsummary> + <desc> + <p>Allocates a new binary of size <c>size</c> bytes. + Initializes the structure pointed to by <c>bin</c> to + refer to the allocated binary. The binary must either be released by + <seealso marker="#enif_release_binary"> + <c>enif_release_binary</c></seealso> + or ownership transferred to an Erlang term with + <seealso marker="#enif_make_binary"><c>enif_make_binary</c></seealso>. + An allocated (and owned) <c>ErlNifBinary</c> can be kept between NIF + calls.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if allocation + fails.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name> + <fsummary>Create a new environment.</fsummary> + <desc> + <p>Allocates a new process-independent environment. The environment can + be used to hold terms that are not bound to any process. Such terms + can later be copied to a process environment with + <seealso marker="#enif_make_copy"><c>enif_make_copy</c></seealso> or + be sent to a process as a message with <seealso marker="#enif_send"> + <c>enif_send</c></seealso>.</p> + <p>Returns pointer to the new environment.</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, - equal, or greater than <c>rhs</c>. Corresponds to the Erlang - operators <c>==</c>, <c>/=</c>, <c>=<</c>, <c><</c>, - <c>>=</c> and <c>></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> - <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> - <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> - <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> - <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> - <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> - <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. - The time is given as a <c>percent</c> of the timeslice that a process is allowed to execute Erlang - code until it may be suspended to give time for other runnable processes. - The scheduling timeslice 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 consumed - CPU time. Lengthy NIFs should regardless of this frequently call <c>enif_consume_timeslice</c> - in order to determine if it is allowed to continue execution or not.</p> - - <p>Returns 1 if the timeslice is exhausted, or 0 otherwise. If 1 is returned the NIF should return - as soon as possible in order for the process to yield.</p> - <p>Argument <c>percent</c> must be an integer between 1 and 100. This function - must only be called from a NIF-calling thread and argument <c>env</c> must be - the environment of the calling process.</p> - <p>This function is provided to better support co-operative scheduling, improve system responsiveness, - and make it easier to prevent misbehaviors of the VM due to a NIF monopolizing a scheduler thread. - It can be used to divide <seealso marker="#lengthy_work">length work</seealso> into - 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> + <name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* + type, unsigned size)</nametext></name> + <fsummary>Allocate a memory-managed resource object.</fsummary> + <desc> + <p>Allocates a memory-managed resource object of type <c>type</c> and + size <c>size</c> bytes.</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> + <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> - <marker id="enif_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_NIF_TIME_ERROR</c> if called with an invalid - time unit argument.</p> - <p>See also: - <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> and - <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>. - </p> + <p>Creates a term that is the result of decoding the binary data at + <c>data</c>, which must be encoded according to the Erlang external + term format. No more than <c>size</c> bytes are read from <c>data</c>. + Argument <c>opts</c> corresponds to the second argument to + <seealso marker="erlang#binary_to_term-2"> + <c>erlang:binary_to_term/2</c></seealso> and must be either <c>0</c> + or <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> + <p>On success, stores the resulting term at <c>*term</c> and returns + the number of bytes read. Returns <c>0</c> if decoding fails or if + <c>opts</c> is invalid.</p> + <p>See also <seealso marker="#ErlNifBinaryToTerm"> + <c>ErlNifBinaryToTerm</c></seealso>, + <seealso marker="erlang#binary_to_term-2"> + <c>erlang:binary_to_term/2</c></seealso>, and + <seealso marker="#enif_term_to_binary"> + <c>enif_term_to_binary</c></seealso>.</p> </desc> </func> <func> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_cpu_time(ErlNifEnv *)</nametext></name> + <name><ret>void</ret><nametext>enif_clear_env(ErlNifEnv* env)</nametext> + </name> + <fsummary>Clear an environment for reuse.</fsummary> + <desc> + <p>Frees all terms in an environment and clears it for reuse. + The environment must have been allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></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>Returns an integer < <c>0</c> if <c>lhs</c> < <c>rhs</c>, + <c>0</c> if <c>lhs</c> = <c>rhs</c>, and > <c>0</c> if + <c>lhs</c> > <c>rhs</c>. Corresponds to the Erlang + operators <c>==</c>, <c>/=</c>, <c>=<</c>, <c><</c>, + <c>>=</c>, and <c>></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> <fsummary></fsummary> <desc> - <p>Returns the CPU time in the same format as <seealso marker="erlang#timestamp-0">erlang:timestamp()</seealso>. - The CPU time is the time the current logical cpu has spent executing since - some arbitrary point in the past. - If the OS does not support fetching of this value <c>enif_cpu_time</c> - invokes <seealso marker="#enif_make_badarg">enif_make_badarg</seealso>. - </p> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast"> + <c>erl_drv_cond_broadcast</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_cond_create</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_cond_destroy</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_cond_signal</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_cond_wait</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_consume_timeslice(ErlNifEnv *env, int percent)</nametext> + </name> + <fsummary></fsummary> + <desc> + <p>Gives the runtime system a hint about how much CPU time the current + NIF call has consumed since the last hint, or since the start of the + NIF if no previous hint has been specified. The time is specified as a + percent of the timeslice that a process is allowed to execute + Erlang code until it can be suspended to give time for other runnable + processes. The scheduling timeslice is not an exact entity, but can + usually be approximated to about 1 millisecond.</p> + <p>Notice that it is up to the runtime system to determine if and how + to use this information. Implementations on some platforms can use + other means to determine consumed CPU time. Lengthy NIFs should + regardless of this frequently call <c>enif_consume_timeslice</c> to + determine if it is allowed to continue execution.</p> + <p>Argument <c>percent</c> must be an integer between 1 and 100. This + function must only be called from a NIF-calling thread, and argument + <c>env</c> must be the environment of the calling process.</p> + <p>Returns <c>1</c> if the timeslice is exhausted, otherwise <c>0</c>. + If <c>1</c> is returned, the NIF is to return as soon as possible in + order for the process to yield.</p> + <p>This function is provided to better support co-operative scheduling, + improve system responsiveness, and make it easier to prevent + misbehaviors of the VM because of a NIF monopolizing a scheduler + thread. It can be used to divide <seealso marker="#lengthy_work"> + length work</seealso> into a number of repeated NIF calls without the + need to create threads.</p> + <p>See also the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this manual page.</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> + <desc> + <marker id="enif_convert_time_unit"></marker> + <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> + <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>Returns <c>ERL_NIF_TIME_ERROR</c> if called with an invalid + time unit argument.</p> + <p>See also <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and + <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_cpu_time(ErlNifEnv *)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Returns the CPU time in the same format as + <seealso marker="erlang#timestamp-0"> + <c>erlang:timestamp()</c></seealso>. + The CPU time is the time the current logical CPU has spent executing + since some arbitrary point in the past. If the OS does not support + fetching this value, <c>enif_cpu_time</c> invokes + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_equal_tids</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_free(void* ptr)</nametext></name> + <fsummary>Free dynamic memory.</fsummary> + <desc> + <p>Frees memory allocated by + <seealso marker="#enif_alloc"><c>enif_alloc</c></seealso>.</p> + </desc> + </func> + + <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>Frees an environment allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></seealso>. + All terms created in the environment are 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> + <fsummary>Get the text representation of an atom term.</fsummary> + <desc> + <p>Writes a <c>NULL</c>-terminated string in the buffer pointed to by + <c>buf</c> of size <c>size</c>, consisting of the string + representation of the atom <c>term</c> with encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>Returns the number of bytes written (including terminating + <c>NULL</c> character) or <c>0</c> if <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> + <fsummary>Get the length of atom <c>term</c>.</fsummary> + <desc> + <p>Sets <c>*len</c> to the length (number of bytes excluding + terminating <c>NULL</c> character) of the atom <c>term</c> with + encoding <c>encode</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read a floating-point number term.</fsummary> + <desc> + <p>Sets <c>*dp</c> to the floating-point value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read an integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read a 64-bit integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read a local pid term.</fsummary> + <desc> + <p>If <c>term</c> is the pid of a node local process, this function + initializes the pid variable <c>*pid</c> from it and returns + <c>true</c>. Otherwise returns <c>false</c>. No check is done to see + if the process is alive.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_local_port(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifPort* port_id)</nametext></name> + <fsummary>Read a local port term.</fsummary> + <desc> + <p>If <c>term</c> identifies a node local port, this function + initializes the port variable <c>*port_id</c> from it and returns + <c>true</c>. Otherwise returns <c>false</c>. No check is done to see + if the port is alive.</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> + <fsummary>Get head and tail from a list.</fsummary> + <desc> + <p>Sets <c>*head</c> and <c>*tail</c> from list <c>list</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if it is + not a list or the list is empty.</p> </desc> </func> - <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> - <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> - <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> - <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 - representation of the atom <c>term</c> with encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. Return - the number of bytes written (including terminating null character) or 0 if - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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, - ERL_NIF_TERM list, char* buf, unsigned size, - ErlNifCharEncoding encode)</nametext></name> - <fsummary>Get a C-string from a list</fsummary> - <desc><p>Write a null-terminated string, in the buffer pointed to by - <c>buf</c> with size <c>size</c>, consisting of the characters - in the string <c>list</c>. The characters are written using encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. - Return the number of bytes written (including terminating null - character), or <c>-size</c> if the string was truncated due to - buffer space, or 0 if <c>list</c> is not a string that can be - encoded with <c>encode</c> or if <c>size</c> was less than 1. - 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> - <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 - <c>*arity</c> to the number of elements. Note that the array - is read-only and <c>(*array)[N-1]</c> will be the Nth element of - the tuple. <c>*array</c> is undefined if the arity of the tuple - 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> - <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> - <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> - <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> - <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> - <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. - Otherwise, if there's a pending exception associated with <c>env</c>, set the ERL_NIF_TERM - to which <c>reason</c> points to the value of the exception's term. For example, if - <seealso marker="#enif_make_badarg">enif_make_badarg</seealso> is called to set a - pending <c>badarg</c> exception, a subsequent call to <c>enif_has_pending_exception(env, &reason)</c> - will set <c>reason</c> to the atom <c>badarg</c>, then return true.</p> - <p>See also: <seealso marker="#enif_make_badarg">enif_make_badarg</seealso> - 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> - <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* - env, ERL_NIF_TERM term, ErlNifBinary* bin) - </nametext></name> - <fsummary>Inspect the content of an iolist</fsummary> - <desc><p>Initialize the structure pointed to by <c>bin</c> with one - continuous buffer with the same byte content as <c>iolist</c>. As with - inspect_binary, the data pointed to by <c>bin</c> is transient and does - not need to be released. Return true on success or false if <c>iolist</c> is not an - iolist.</p> + <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>Sets <c>*len</c> to the length of list <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read a long integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the long integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read the size of a map term.</fsummary> + <desc> + <p>Sets <c>*size</c> to the number of key-value pairs in the map + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Get the value of a key in a map.</fsummary> + <desc> + <p>Sets <c>*value</c> to the value associated with <c>key</c> in the + map <c>map</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Get the pointer to a resource object.</fsummary> + <desc> + <p>Sets <c>*objp</c> to point to the resource object referred to by + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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, + ERL_NIF_TERM list, char* buf, unsigned size, + ErlNifCharEncoding encode)</nametext></name> + <fsummary>Get a C-string from a list.</fsummary> + <desc> + <p>Writes a <c>NULL</c>-terminated string in the buffer pointed to by + <c>buf</c> with size <c>size</c>, consisting of the characters + in the string <c>list</c>. The characters are written using encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>Returns one of the following:</p> + <list type="bulleted"> + <item>The number of bytes written (including terminating <c>NULL</c> + character)</item> + <item><c>-size</c> if the string was truncated because of buffer + space</item> + <item><c>0</c> if <c>list</c> is not a string that can be encoded + with <c>encode</c> or if <c>size</c> was < <c>1</c>.</item> + </list> + <p>The written string is always <c>NULL</c>-terminated, unless buffer + <c>size</c> is < <c>1</c>.</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> + <fsummary>Inspect the elements of a tuple.</fsummary> + <desc> + <p>If <c>term</c> is a tuple, this function sets <c>*array</c> to point + to an array containing the elements of the tuple, and sets + <c>*arity</c> to the number of elements. Notice that the array + is read-only and <c>(*array)[N-1]</c> is the Nth element of + the tuple. <c>*array</c> is undefined if the arity of the tuple + is zero.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read an unsigned integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the unsigned integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read an unsigned 64-bit integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the unsigned integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Read an unsigned integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the unsigned long integer value of + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> 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> + <fsummary>Get the value of an environment variable.</fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_getenv"> + <c>erl_drv_getenv</c></seealso>.</p> + </desc> + </func> + + <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>Returns <c>true</c> if a pending exception is associated with the + environment <c>env</c>. If <c>reason</c> is a <c>NULL</c> pointer, + ignore it. Otherwise, if a pending exception associated with + <c>env</c> exists, set <c>ERL_NIF_TERM</c> to which <c>reason</c> + points to the value of the exception's term. For example, if + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso> is called to set a pending + <c>badarg</c> exception, a later call to + <c>enif_has_pending_exception(env, &reason)</c> sets + <c>reason</c> to the atom <c>badarg</c>, then return <c>true</c>.</p> + <p>See also <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso> and + <seealso marker="#enif_raise_exception"> + <c>enif_raise_exception</c></seealso>.</p> + </desc> + </func> + + <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>Initializes the structure pointed to by <c>bin</c> with information + about binary term <c>bin_term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>bin_term</c> + is not a binary.</p> </desc> </func> - <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> + <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> + <desc> + <p>Initializes the structure pointed to by <c>bin</c> with a + continuous buffer with the same byte content as <c>iolist</c>. As + with <c>inspect_binary</c>, the data pointed to by <c>bin</c> is + transient and does not need to be released.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>iolist</c> is + not an iolist.</p> + </desc> </func> - <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> + <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>Returns <c>true</c> if <c>term</c> is an atom.</p> + </desc> </func> - <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> + <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>Returns <c>true</c> if <c>term</c> is a binary.</p> + </desc> </func> - <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> + <name><ret>int</ret> + <nametext>enif_is_current_process_alive(ErlNifEnv* env)</nametext> + </name> + <fsummary>Determine if currently executing process is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if the currently executing process is currently + alive, otherwise <c>false</c>.</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_exception(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is an exception</fsummary> + + <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>Returns <c>true</c> 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> + <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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>. - Each call to <c>enif_keep_resource</c> for an object must be balanced by - 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> - <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 - allowed for an atom (255 characters), <c>enif_make_atom</c> invokes - <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> - <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 - allowed for an atom (255 characters), <c>enif_make_atom</c> invokes - <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> - <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 - it calls invokes <c>enif_make_badarg</c>, the runtime ensures that a - <c>badarg</c> exception is raised when the NIF returns, even if the NIF - attempts to return a non-exception term instead. - The return value from <c>enif_make_badarg</c> may be used only as the - return value from the NIF that invoked it (directly or indirectly) - or be passed 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_raise_exception">enif_raise_exception</seealso>. - </p> - <note><p>In earlier versions (older than erts-7.0, OTP 18) the return value - from <c>enif_make_badarg</c> had to be returned from the NIF. This - 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> - <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> - <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> - <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> - <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 - <seealso marker="#ErlNifCharEncoding">encode</seealso>. If the atom - already exists store the term in <c>*atom</c> and return true, otherwise - return false. If the length of <c>name</c> exceeds the maximum length - 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> - <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 - <seealso marker="#ErlNifCharEncoding">encode</seealso>. Null-characters - are treated as any other characters. If the atom already exists store the term - in <c>*atom</c> and return true, otherwise return false. If <c>len</c> is greater - 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> - <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> - <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> - <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> - <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> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> - <fsummary>Create a list term</fsummary> - <desc><p>Create an ordinary list term with length indicated by the - function name. Prefer these functions (macros) over the variadic - <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> - <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> - <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> - <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> - <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 - associated value is replaced by <c>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.</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> - <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 - value. If map <c>map_in</c> does not contain <c>key</c>, set - <c>*map_out</c> to <c>map_in</c>. Return true for success or false if - <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> - <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> - <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> - <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>. - No ownership transfer is done, as the resource object still needs to be released by - <seealso marker="#enif_release_resource">enif_release_resource</seealso>, - but note that the call to <c>enif_release_resource</c> can occur - immediately after obtaining the term from <c>enif_make_resource</c>, - in which case the resource object will be deallocated when the - term is garbage collected. See the - <seealso marker="#enif_resource_example">example of creating and - returning a resource object</seealso> for more details.</p> - <p>Note that the only defined behaviour of using a resource term in - an Erlang program is to store it and send it between processes on the - 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> - <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>. - The returned binary term will consist of <c>size</c> bytes pointed to - by <c>data</c>. This raw binary data must be kept readable and unchanged - until the destructor of the resource is called. The binary data may be - stored external to the resource object in which case it is the responsibility - of the destructor to release the data.</p> - <p>Several binary terms may be managed by the same resource object. The - destructor will not be called until the last binary is garbage collected. - This can be useful as a way to return different parts of a larger binary - buffer.</p> - <p>As with <seealso marker="#enif_make_resource">enif_make_resource</seealso>, - no ownership transfer is done. The resource still needs to be released with - <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> - <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 - short lists as a copy will be created of the list which will not be released until after the - 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> - <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> - <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* - 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 - zero-based position <c>pos</c> with a length of <c>size</c> bytes. - <c>bin_term</c> must be a binary or bitstring and - <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> - <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> - <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> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> - <fsummary>Create a tuple term</fsummary> - <desc><p>Create a tuple term with length indicated by the - function name. Prefer these functions (macros) over the variadic - <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> - <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> - <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> - <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_unique_integer(ErlNifEnv *env, ErlNifUniqueInteger properties)</nametext></name> + <p>Return true if <c>term</c> is an exception.</p> + </desc> + </func> + + <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>Returns <c>true</c> 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> + <fsummary>Erlang operator =:=.</fsummary> + <desc> + <p>Returns <c>true</c> 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_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a list.</fsummary> + <desc> + <p>Returns <c>true</c> 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>Returns <c>true</c> if <c>term</c> is a map, otherwise + <c>false</c>.</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>Returns <c>true</c> 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>Returns <c>true</c> 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> + <fsummary>Determine if a term is a port.</fsummary> + <desc> + <p>Returns <c>true</c> 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> + <fsummary>Determine if a local port is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>port_id</c> is 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> + <fsummary>Determine if a local process is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>pid</c> is 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> + <fsummary>Determine if a term is a reference.</fsummary> + <desc> + <p>Returns <c>true</c> 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> + <fsummary>Determine if a term is a tuple.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a tuple.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_keep_resource(void* obj)</nametext> + </name> + <fsummary>Add a reference to a resource object.</fsummary> + <desc> + <p>Adds a reference to resource object <c>obj</c> obtained from + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. Each call to + <c>enif_keep_resource</c> for an object must be balanced by a call to + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso> + before the object is destructed.</p> + </desc> + </func> + + <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>Creates an atom term from the <c>NULL</c>-terminated C-string + <c>name</c> with ISO Latin-1 encoding. If the length of <c>name</c> + exceeds the maximum length allowed for an atom (255 characters), + <c>enif_make_atom</c> invokes <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></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> + <fsummary>Create an atom term.</fsummary> + <desc> + <p>Create an atom term from the string <c>name</c> with length + <c>len</c>. <c>NULL</c> characters are treated as any other + characters. If <c>len</c> exceeds the maximum length + allowed for an atom (255 characters), <c>enif_make_atom</c> invokes + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_badarg(ErlNifEnv* env)</nametext></name> + <fsummary>Make a badarg exception.</fsummary> + <desc> + <p>Makes a <c>badarg</c> exception to be returned from a NIF, and + associates it with environment <c>env</c>. Once a NIF or any function + it calls invokes <c>enif_make_badarg</c>, the runtime ensures that a + <c>badarg</c> exception is raised when the NIF returns, even if the + NIF attempts to return a non-exception term instead.</p> + <p>The return value from <c>enif_make_badarg</c> can be used only as + the return value from the NIF that invoked it (directly or indirectly) + or be passed to <seealso marker="#enif_is_exception"> + <c>enif_is_exception</c></seealso>, but not to any other NIF API + function.</p> + <p>See also <seealso marker="#enif_has_pending_exception"> + <c>enif_has_pending_exception</c></seealso> and + <seealso marker="#enif_raise_exception"> + <c>enif_raise_exception</c></seealso>.</p> + <note> + <p>Before <c>ERTS</c> 7.0 (Erlang/OTP 18), the return value + from <c>enif_make_badarg</c> had to be returned from the NIF. This + 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> + <fsummary>Make a binary term.</fsummary> + <desc> + <p>Makes a binary term from <c>bin</c>. Any ownership of + the binary data is transferred to the created term and + <c>bin</c> is to 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> + <fsummary>Make a copy of a term.</fsummary> + <desc> + <p>Makes a copy of term <c>src_term</c>. The copy is created in + environment <c>dst_env</c>. The source term can 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> + <fsummary>Create a floating-point term.</fsummary> + <desc> + <p>Creates a floating-point term from a <c>double</c>. If argument + <c>double</c> is not finite or is NaN, <c>enif_make_double</c> + invokes <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></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> + <fsummary>Create an existing atom term.</fsummary> + <desc> + <p>Tries to create the term of an already existing atom from + the <c>NULL</c>-terminated C-string <c>name</c> with encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>If the atom already exists, this function stores the term in + <c>*atom</c> and returns <c>true</c>, otherwise <c>false</c>. + Also returns <c>false</c> if the length of <c>name</c> exceeds the + maximum length allowed for an atom (255 characters).</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> + <fsummary>Create an existing atom term.</fsummary> + <desc> + <p>Tries to create the term of an already existing atom from the + string <c>name</c> with length <c>len</c> and encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>. <c>NULL</c> + characters are treated as any other characters.</p> + <p>If the atom already exists, this function stores the term in + <c>*atom</c> and returns <c>true</c>, otherwise <c>false</c>. + Also returns <c>false</c> if <c>len</c> exceeds the maximum length + allowed for an atom (255 characters).</p> + </desc> + </func> + + <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>Creates an integer term.</p> + </desc> + </func> + + <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>Creates 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> + <fsummary>Create a list term.</fsummary> + <desc> + <p>Creates an ordinary list term of length <c>cnt</c>. Expects + <c>cnt</c> number of arguments (after <c>cnt</c>) of type + <c>ERL_NIF_TERM</c> as the elements of the list.</p> + <p>Returns an empty list 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> + <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> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> + <fsummary>Create a list term.</fsummary> + <desc> + <p>Creates an ordinary list term with length indicated by the + function name. Prefer these functions (macros) over the variadic + <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> + <fsummary>Create a list cell.</fsummary> + <desc> + <p>Creates 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> + <fsummary>Create a list term from an array.</fsummary> + <desc> + <p>Creates an ordinary list containing the elements of array <c>arr</c> + of length <c>cnt</c>.</p> + <p>Returns an empty list 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> + <fsummary>Create an integer term from a long int.</fsummary> + <desc> + <p>Creates an integer term from a <c>long int</c>.</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> + <fsummary>Insert key-value pair in map.</fsummary> + <desc> + <p>Makes a copy of map <c>map_in</c> and inserts <c>key</c> with + <c>value</c>. If <c>key</c> already exists in <c>map_in</c>, the old + associated value is replaced by <c>value</c>.</p> + <p>If successful, this function sets <c>*map_out</c> to the new map and + returns <c>true</c>. Returns <c>false</c> if <c>map_in</c> is not a + map.</p> + <p>The <c>map_in</c> term must belong to 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> + <fsummary>Remove key from map.</fsummary> + <desc> + <p>If map <c>map_in</c> contains <c>key</c>, this function makes a copy + of <c>map_in</c> in <c>*map_out</c>, and removes <c>key</c> and the + associated value. If map <c>map_in</c> does not contain <c>key</c>, + <c>*map_out</c> is set to <c>map_in</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>map_in</c> is + not a map.</p> + <p>The <c>map_in</c> term must belong to 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>Makes a copy of map <c>map_in</c> and replace the old associated + value for <c>key</c> with <c>new_value</c>.</p> + <p>If successful, this function sets <c>*map_out</c> to the new map and + returns <c>true</c>. Returns <c>false</c> if <c>map_in</c> is not a + map or if it does not contain <c>key</c>.</p> + <p>The <c>map_in</c> term must belong to 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>Allocates a binary of size <c>size</c> bytes and creates 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"><c>ErlNifBinary</c></seealso>. + The drawbacks are that the binary cannot be kept between NIF calls + and it cannot be reallocated.</p> + <p>Returns a pointer to the raw binary data and sets + <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>Makes 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>Makes 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> + <fsummary>Create a reference.</fsummary> + <desc> + <p>Creates a reference like <seealso marker="erlang#make_ref-0"> + <c>erlang:make_ref/0</c></seealso>.</p> + </desc> + </func> + + <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>Creates an opaque handle to a memory-managed resource object + obtained by <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. No ownership transfer is done, + as the resource object still needs to be released by + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso>. However, notice that the call + to <c>enif_release_resource</c> can occur immediately after obtaining + the term from <c>enif_make_resource</c>, in which case the resource + object is deallocated when the term is garbage collected. For more + details, see the <seealso marker="#enif_resource_example">example of + creating and returning a resource object</seealso> in the User's + Guide.</p> + <p>Notice that the only defined behavior of using a resource term in + an Erlang program is to store it and send it between processes on the + same node. Other operations, such as matching or + <c>term_to_binary</c>, 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> + <fsummary>Create a custom binary term.</fsummary> + <desc> + <p>Creates a binary term that is memory-managed by a resource object + <c>obj</c> obtained by <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. The returned binary term + consists of <c>size</c> bytes pointed to by <c>data</c>. This raw + binary data must be kept readable and unchanged until the destructor + of the resource is called. The binary data can be stored external to + the resource object, in which case the destructor is responsible + for releasing the data.</p> + <p>Several binary terms can be managed by the same resource object. The + destructor is not called until the last binary is garbage collected. + This can be useful to return different parts of a larger binary + buffer.</p> + <p>As with <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso>, no ownership transfer is done. + The resource still needs to be released with + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></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> + <fsummary>Create the reverse of a list.</fsummary> + <desc> + <p>Sets <c>*list_out</c> to the reverse list of the list <c>list_in</c> + and returns <c>true</c>, or returns <c>false</c> if <c>list_in</c> is + not a list.</p> + <p>This function is only to be used on short lists, as a copy is + created of the list, which is not released until after the NIF + returns.</p> + <p>The <c>list_in</c> term must belong to 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> + <fsummary>Create a string.</fsummary> + <desc> + <p>Creates a list containing the characters of the + <c>NULL</c>-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> + <fsummary>Create a string.</fsummary> + <desc> + <p>Creates a list containing the characters of the string <c>string</c> + with length <c>len</c> and encoding + <seealso marker="#ErlNifCharEncoding">encoding</seealso>. + <c>NULL</c> characters are treated as any other characters.</p> + </desc> + </func> + + <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>Makes a subbinary of binary <c>bin_term</c>, starting at + zero-based position <c>pos</c> with a length of <c>size</c> bytes. + <c>bin_term</c> must be a binary or bitstring. <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> + <fsummary>Creates a tuple term.</fsummary> + <desc> + <p>Creates a tuple term of arity <c>cnt</c>. Expects <c>cnt</c> number + of arguments (after <c>cnt</c>) of type <c>ERL_NIF_TERM</c> 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> + <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> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> + <fsummary>Create a tuple term.</fsummary> + <desc> + <p>Creates a tuple term with length indicated by the + function name. Prefer these functions (macros) over the variadic + <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> + <fsummary>Create a tuple term from an array.</fsummary> + <desc> + <p>Creates 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> + <fsummary>Create an unsigned integer term.</fsummary> + <desc> + <p>Creates 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> + <fsummary>Create an unsigned integer term.</fsummary> + <desc> + <p>Creates 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>Creates 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> <desc> - <p>Returns a unique integer with the same properties as given by <seealso marker="erlang#unique_integer-1">erlang:unique_integer/1</seealso>.</p> + <p>Returns a unique integer with the same properties as specified by + <seealso marker="erlang#unique_integer-1"> + <c>erlang:unique_integer/1</c></seealso>.</p> <p><c>env</c> is the environment to create the integer in.</p> - <p> - <c>ERL_NIF_UNIQUE_POSITIVE</c> and <c>ERL_NIF_UNIQUE_MONOTONIC</c> can - be passed as the second argument to change the properties of the - integer returned. It is possible to combine them by or:ing the - two values together. - </p> - <p>See also: - <seealso marker="#ErlNifUniqueInteger"><c>ErlNifUniqueInteger</c></seealso>. - </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> - <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 - the start position of the iterator: <c>ERL_NIF_MAP_ITERATOR_FIRST</c> or - <c>ERL_NIF_MAP_ITERATOR_LAST</c>. Return true on success or false if - <c>map</c> is not a map.</p> - <p>A map iterator is only useful during the lifetime of the environment - <c>env</c> that the <c>map</c> belongs to. The iterator must be destroyed by - calling <seealso marker="#enif_map_iterator_destroy"> - enif_map_iterator_destroy</seealso>.</p> - <code type="none"> + <p><c>ERL_NIF_UNIQUE_POSITIVE</c> and <c>ERL_NIF_UNIQUE_MONOTONIC</c> + can be passed as the second argument to change the properties of the + integer returned. They can be combined by OR:ing the two values + together.</p> + <p>See also <seealso marker="#ErlNifUniqueInteger"> + <c>ErlNifUniqueInteger</c></seealso>.</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> + <fsummary>Create a map iterator.</fsummary> + <desc> + <p>Creates an iterator for the map <c>map</c> by initializing the + structure pointed to by <c>iter</c>. Argument <c>entry</c> determines + the start position of the iterator: <c>ERL_NIF_MAP_ITERATOR_FIRST</c> + or <c>ERL_NIF_MAP_ITERATOR_LAST</c>.</p> + <p>Returns <c>true</c> on success, or false if <c>map</c> is not a + map.</p> + <p>A map iterator is only useful during the lifetime of environment + <c>env</c> that the <c>map</c> belongs to. The iterator must be + destroyed by calling <seealso marker="#enif_map_iterator_destroy"> + <c>enif_map_iterator_destroy</c></seealso>:</p> + <code type="none"> ERL_NIF_TERM key, value; ErlNifMapIterator iter; enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST); @@ -1468,439 +2070,714 @@ while (enif_map_iterator_get_pair(env, &iter, &key, &value)) { do_something(key,value); enif_map_iterator_next(env, &iter); } -enif_map_iterator_destroy(env, &iter); - </code> - <note><p>The key-value pairs of a map have no defined iteration - order. The only guarantee is that the iteration order of a single map - instance is preserved during the lifetime of the environment that the map - belongs to.</p> - </note> +enif_map_iterator_destroy(env, &iter);</code> + <note> + <p>The key-value pairs of a map have no defined iteration order. + The only guarantee is that the iteration order of a single map + instance is preserved during the lifetime of the environment that + the map belongs to.</p> + </note> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_map_iterator_destroy(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Destroy a map iterator.</fsummary> + <desc> + <p>Destroys a map iterator created by + <seealso marker="#enif_map_iterator_create"> + <c>enif_map_iterator_create</c></seealso>.</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> + <fsummary>Get key and value at current map iterator position.</fsummary> + <desc> + <p>Gets key and value terms at the current map iterator position.</p> + <p>On success, sets <c>*key</c> and <c>*value</c> and returns + <c>true</c>. Returns <c>false</c> if the iterator is positioned at + head (before first entry) 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> + <fsummary>Check if map iterator is positioned before first.</fsummary> + <desc> + <p>Returns <c>true</c> if map iterator <c>iter</c> is positioned + before the first entry.</p> + </desc> + </func> + + <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>Returns <c>true</c> if map iterator <c>iter</c> is positioned + after the last entry.</p> + </desc> + </func> + + <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>Increments map iterator to point to the next key-value entry.</p> + <p>Returns <c>true</c> if the iterator is now positioned at a valid + key-value entry, or <c>false</c> if the iterator is positioned at + the tail (beyond the last entry).</p> + </desc> + </func> + + <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>Decrements map iterator to point to the previous key-value entry.</p> + <p>Returns <c>true</c> if the iterator is now positioned at a valid + key-value entry, or <c>false</c> if the iterator is positioned at + the head (before the first entry).</p> + </desc> + </func> + + <func> + <name><ret>ErlNifTime</ret> + <nametext>enif_monotonic_time(ErlNifTimeUnit time_unit)</nametext> + </name> + <fsummary>Get Erlang monotonic time.</fsummary> + <desc> + <marker id="enif_monotonic_time"></marker> + <p>Returns the current + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso>. Notice that it is not uncommon with + negative values.</p> + <p><c>time_unit</c> is the time unit of the returned value.</p> + <p>Returns <c>ERL_NIF_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 <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>. + </p> + </desc> + </func> + + <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"> + <c>erl_drv_mutex_create</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_mutex_destroy</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_mutex_lock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_mutex_trylock</c></seealso>.</p> </desc> </func> - <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 - <seealso marker="#enif_map_iterator_create">enif_map_iterator_create</seealso>. - </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> - <fsummary>Get key and value at current map iterator position</fsummary> - <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> - </func> - <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> - </func> - <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> - </func> - <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. - 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> - </func> - <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. - 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> - </func> - - <func> - <name><ret>ErlNifTime</ret><nametext>enif_monotonic_time(ErlNifTimeUnit time_unit)</nametext></name> - <fsummary>Get Erlang Monotonic Time</fsummary> - <desc> - <marker id="enif_monotonic_time"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>time_unit</c></tag> - <item>Time unit of returned value.</item> - </taglist> - <p> - Returns the current - <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_NIF_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: - <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> and - <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>. - </p> - </desc> - </func> - - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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 - <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> - <tag><c>ERL_NIF_RT_CREATE</c></tag> - <item>Create a new resource type that does not already exist.</item> - <tag><c>ERL_NIF_RT_TAKEOVER</c></tag> - <item>Open an existing resource type and take over ownership of all its instances. - The supplied destructor <c>dtor</c> will be called both for existing instances - as well as new instances not yet created by the calling NIF library.</item> - </taglist> - <p>The two flag values can be combined with bitwise-or. The name of the - resource type is local to the calling module. Argument <c>module_str</c> - is not (yet) used and must be NULL. The <c>dtor</c> may be <c>NULL</c> - in case no destructor is needed.</p> - <p>On success, return a pointer to the resource type and <c>*tried</c> - will be set to either <c>ERL_NIF_RT_CREATE</c> or - <c>ERL_NIF_RT_TAKEOVER</c> to indicate what was actually done. - On failure, return <c>NULL</c> and set <c>*tried</c> to <c>flags</c>. - It is allowed to set <c>tried</c> to <c>NULL</c>.</p> - <p>Note that <c>enif_open_resource_type</c> is only allowed to be called in the three callbacks - <seealso marker="#load">load</seealso>, <seealso marker="#reload">reload</seealso> - 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> - <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> - except that it is always completely asynchronous.</p> + + <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"> + <c>erl_drv_mutex_unlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_now_time(ErlNifEnv *env)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Returns an <seealso marker="erlang#now-0"> + <c>erlang:now()</c></seealso> time stamp.</p> + <p><em>This function is deprecated.</em></p> + </desc> + </func> + + <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>Creates or takes over a resource type identified by the string + <c>name</c> and gives it the destructor function pointed to by + <seealso marker="#ErlNifResourceDtor"><c>dtor</c></seealso>. + Argument <c>flags</c> can have the following values:</p> + <taglist> + <tag><c>ERL_NIF_RT_CREATE</c></tag> + <item>Creates a new resource type that does not already exist.</item> + <tag><c>ERL_NIF_RT_TAKEOVER</c></tag> + <item>Opens an existing resource type and takes over ownership of all + its instances. The supplied destructor <c>dtor</c> is called both + for existing instances and new instances not yet created by the + calling NIF library.</item> + </taglist> + <p>The two flag values can be combined with bitwise OR. The resource + type name is local to the calling module. Argument <c>module_str</c> + is not (yet) used and must be <c>NULL</c>. <c>dtor</c> can be + <c>NULL</c> if no destructor is needed.</p> + <p>On success, the function returns a pointer to the resource type and + <c>*tried</c> is set to either <c>ERL_NIF_RT_CREATE</c> or + <c>ERL_NIF_RT_TAKEOVER</c> to indicate what was done. On failure, + returns <c>NULL</c> and sets <c>*tried</c> to <c>flags</c>. + It is allowed to set <c>tried</c> to <c>NULL</c>.</p> + <p>Notice that <c>enif_open_resource_type</c> is only allowed to be + called in the three callbacks + <seealso marker="#load"><c>load</c></seealso>, + <seealso marker="#reload"><c>reload</c></seealso>, and + <seealso marker="#upgrade"><c>upgrade</c></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> + <fsummary>Send a port_command to to_port.</fsummary> + <desc> + <p>Works as <seealso marker="erlang#port_command-2"> + <c>erlang:port_command/2</c></seealso>, + except that it is always completely asynchronous.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must not be + <c>NULL</c>.</item> + <tag><c>*to_port</c></tag> + <item>The port ID of the receiving port. The port ID is to refer to a + port on the local node.</item> + <tag><c>msg_env</c></tag> + <item>The environment of the message term. Can be a process-independent + environment allocated with <seealso marker="#enif_alloc_env"> + <c>enif_alloc_env</c></seealso> or <c>NULL</c>.</item> + <tag><c>msg</c></tag> + <item>The message term to send. The same limitations apply as on the + payload to <seealso marker="erlang#port_command-2"> + <c>erlang:port_command/2</c></seealso>.</item> + </taglist> + <p>Using a <c>msg_env</c> of <c>NULL</c> is an optimization, which + groups together calls to <c>enif_alloc_env</c>, <c>enif_make_copy</c>, + <c>enif_port_command</c>, and <c>enif_free_env</c> into one call. + This optimization is only useful when a majority of the terms are to + be copied from <c>env</c> to <c>msg_env</c>.</p> + <p>Returns <c>true</c> if the command is successfully sent. Returns + <c>false</c> if the command fails, for example:</p> + <list type="bulleted"> + <item><c>*to_port</c> does not refer to a local port.</item> + <item>The currently executing process (that is, the sender) is not + alive.</item> + <item><c>msg</c> is invalid.</item> + </list> + <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> + <fsummary>Get the private data of a NIF library.</fsummary> + <desc> + <p>Returns the pointer to the private data that was set by + <seealso marker="#load"><c>load</c></seealso>, + <seealso marker="#reload"><c>reload</c></seealso>, or + <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> + <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> + <fsummary>Raise a NIF error exception.</fsummary> + <desc> + <p>Creates an error exception with the term <c>reason</c> to be + returned from a NIF, and associates it with 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 term instead.</p> + <p>The return value from <c>enif_raise_exception</c> can only be used + as the return value from the NIF that invoked it (directly or + indirectly) or be passed to <seealso marker="#enif_is_exception"> + <c>enif_is_exception</c></seealso>, but not to any other NIF API + function.</p> + <p>See also <seealso marker="#enif_has_pending_exception"> + <c>enif_has_pending_exception</c></seealso> and + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <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>Changes the size of a binary <c>bin</c>. The source binary + can be read-only, in which case it is left untouched and + a mutable copy is allocated and assigned to <c>*bin</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if memory allocation + failed.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_release_binary(ErlNifBinary* bin)</nametext></name> + <fsummary>Release a binary.</fsummary> + <desc> + <p>Releases a binary obtained from + <seealso marker="#enif_alloc_binary"> + <c>enif_alloc_binary</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_release_resource(void* obj)</nametext></name> + <fsummary>Release a resource object.</fsummary> + <desc> + <p>Removes a reference to resource object <c>obj</c>obtained from + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. + The resource object is 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"> + <c>enif_keep_resource</c></seealso>. + References made by <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso> + can only be removed by the garbage collector.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_create</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_destroy</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_rlock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_runlock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_rwlock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_rwunlock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_tryrlock</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_rwlock_tryrwlock</c></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> + <fsummary>Schedule a NIF for execution.</fsummary> + <desc> + <p>Schedules NIF <c>fp</c> to execute. This function allows an + application to break up long-running work into multiple regular NIF + calls or to schedule a <seealso marker="#dirty_nifs"> + dirty NIF</seealso> to execute on a dirty scheduler thread.</p> + <p><em>The dirty NIF functionality described here is + experimental.</em> You have to enable support for dirty + schedulers when building OTP to try out the functionality.</p> + <taglist> + <tag><c>fun_name</c></tag> + <item> + <p>Provides a name for the NIF that is scheduled for execution. + If it cannot be converted to an atom, <c>enif_schedule_nif</c> + returns a <c>badarg</c> exception.</p> + </item> + <tag><c>flags</c></tag> + <item> + <p>Must be set to <c>0</c> for a regular NIF. If the emulator was + built with the experimental dirty scheduler support enabled, + <c>flags</c> can be set to either + <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> if the job is expected to be + CPU-bound, or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c> for + jobs that will be I/O-bound. If dirty scheduler threads are not + available in the emulator, an attempt to schedule such a job + results in a <c>badarg</c> exception.</p> + </item> + <tag><c>argc</c> and <c>argv</c></tag> + <item> + <p>Can either be the originals passed into the calling NIF, + or can be values created by the calling NIF.</p> + </item> + </taglist> + <p>The calling NIF must use the return value of + <c>enif_schedule_nif</c> as its own return value.</p> + <p>Be aware that <c>enif_schedule_nif</c>, as its name implies, only + schedules the NIF for future execution. The calling NIF does not + block waiting for the scheduled NIF to execute and return. This means + that the calling NIF cannot expect to receive the scheduled NIF + 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> + <fsummary>Get the pid of the calling process.</fsummary> + <desc> + <p>Initializes the pid variable <c>*pid</c> to represent the + calling process.</p> + <p>Returns <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> + <fsummary>Send a message to a process.</fsummary> + <desc> + <p>Sends a message to a process.</p> <taglist> <tag><c>env</c></tag> - <item>The environment of the calling process. May not be NULL.</item> - <tag><c>*to_port</c></tag> - <item>The port id of the receiving port. The port id should refer to a - port on the local node.</item> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>*to_pid</c></tag> + <item>The pid of the receiving process. The pid is to refer to a + process on the local node.</item> <tag><c>msg_env</c></tag> - <item>The environment of the message term. Can be a process - independent environment allocated with - <seealso marker="#enif_alloc_env">enif_alloc_env</seealso> or NULL.</item> + <item>The environment of the message term. Must be a + process-independent environment allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></seealso> + or NULL.</item> <tag><c>msg</c></tag> - <item>The message term to send. The same limitations apply as on the - payload to <seealso marker="erlang#port_command-2">erlang:port_command/2</seealso>.</item> + <item>The message term to send.</item> </taglist> - <p>Using a <c>msg_env</c> of NULL is an optimization which groups together - calls to <c>enif_alloc_env</c>, <c>enif_make_copy</c>, <c>enif_port_command</c> - and <c>enif_free_env</c> into one call. This optimization is only usefull - when a majority of the terms are to be copied from <c>env</c> to the <c>msg_env</c>.</p> - <p>This function return true if the command was successfully sent; otherwise, - false. The call may return false if it detects that the command failed for some - reason. For example, <c>*to_port</c> does not refer to a local port, if currently - executing process, i.e. the sender, is not alive, or if <c>msg</c> is invalid.</p> - <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> - <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>, - <c>reload</c> or <c>upgrade</c>.</p> - <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> - <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, - 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 - term instead. The return value from <c>enif_raise_exception</c> may be used only as - the return value from the NIF that invoked it (directly or indirectly) or be passed - 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> - </func> - <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 - 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> - </func> - <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> - </func> - <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 - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </func> - <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> - </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> - <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 - work into multiple regular NIF calls or to schedule a <seealso marker="#dirty_nifs">dirty NIF</seealso> - to execute on a dirty scheduler thread (<em>note that the dirty NIF functionality described here is - experimental</em> and that you have to enable support for dirty schedulers when building OTP in - order to try the functionality out).</p> - <p>The <c>fun_name</c> argument provides a name for the NIF being scheduled for execution. If it cannot - be converted to an atom, <c>enif_schedule_nif</c> returns a <c>badarg</c> exception.</p> - <p>The <c>flags</c> argument must be set to 0 for a regular NIF, or if the emulator was built the - experimental dirty scheduler support enabled, <c>flags</c> can be set to either <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> - if the job is expected to be CPU-bound, or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c> for jobs that will - be I/O-bound. If dirty scheduler threads are not available in the emulator, a try to schedule such a job - will result in a <c>badarg</c> exception.</p> - - <p>The <c>argc</c> and <c>argv</c> arguments can either be the originals passed into the calling NIF, or - they can be values created by the calling NIF.</p> - <p>The calling NIF must use the return value of <c>enif_schedule_nif</c> as its own return value.</p> - <p>Be aware that <c>enif_schedule_nif</c>, as its name implies, only schedules the - NIF for future execution. The calling NIF does not block waiting for the scheduled NIF to - execute and return, which means that the calling NIF can't expect to receive the scheduled NIF - return value and use it for further operations.</p> + <p>Returns <c>true</c> if the message is successfully sent. Returns + <c>false</c> if the send operation fails, that is:</p> + <list type="bulleted"> + <item><c>*to_pid</c> does not refer to an alive local process.</item> + <item>The currently executing process (that is, the sender) is not + alive.</item> + </list> + <p>The message environment <c>msg_env</c> with all its terms (including + <c>msg</c>) is invalidated by a successful call to <c>enif_send</c>. + The environment is to either be freed with + <seealso marker="#enif_free_env"> + <c>enif_free_env</c></seealso> of cleared for reuse with + <seealso marker="#enif_clear_env"><c>enif_clear_env</c></seealso>.</p> + <p>If <c>msg_env</c> is set to <c>NULL</c>, the <c>msg</c> term is + copied and the original term and its environemt is still valid after + the call.</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> + <note> + <p>Passing <c>msg_env</c> as <c>NULL</c> is only supported as from + <c>ERTS</c> 8.0 (Erlang/OTP 19).</p> + </note> + </desc> + </func> + + <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>Gets the byte size of resource object <c>obj</c> obtained by + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>.</p> + </desc> + </func> + + <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.</p> + </desc> + </func> + + <func> + <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"> + <c>driver_system_info</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>enif_alloc_binary</c></seealso> and stores the result of encoding + <c>term</c> according to the Erlang external term format.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if the allocation + fails.</p> + <p>See also <seealso marker="erlang#term_to_binary-1"> + <c>erlang:term_to_binary/1</c></seealso> and + <seealso marker="#enif_binary_to_term"> + <c>enif_binary_to_term</c></seealso>.</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> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_thread_exit</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_thread_join</c></seealso>.</p> </desc> </func> - <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> - </func> - <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> - <taglist> - <tag><c>env</c></tag> - <item>The environment of the calling process. Must be NULL if and - only if calling from a created thread.</item> - <tag><c>*to_pid</c></tag> - <item>The pid of the receiving process. The pid should refer to a process on the local node.</item> - <tag><c>msg_env</c></tag> - <item>The environment of the message term. Must be a process - independent environment allocated with - <seealso marker="#enif_alloc_env">enif_alloc_env</seealso> or NULL.</item> - <tag><c>msg</c></tag> - <item>The message term to send.</item> - </taglist> - <p>Return true if the message was successfully sent; otherwise, false. The send - operation will fail if <c>*to_pid</c> does not refer to an alive local process, - or if currently executing process, i.e. the sender, is not alive.</p> - <p>The message environment <c>msg_env</c> with all its terms (including - <c>msg</c>) will be invalidated by a successful call to <c>enif_send</c>. The environment - should either be freed with <seealso marker="#enif_free_env">enif_free_env</seealso> - of cleared for reuse with <seealso marker="#enif_clear_env">enif_clear_env</seealso>.</p> - <p>If <c>msg_env</c> is set to NULL the <c>msg</c> term is copied and - the original term and its environemt is still valid after the call.</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> - <note><p>Passing <c>msg_env</c> as <c>NULL</c> is only supported since - erts-8.0 (OTP 19).</p></note> - </desc> - </func> - <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> - </func> - - <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. - </p> - </desc> - </func> - - <func> - <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> - </func> - <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> - and stores the result of encoding <c>term</c> according to the Erlang external term format.</p> - <p>Returns true on success or false if allocation failed.</p> - <p>See also: - <seealso marker="erlang#term_to_binary-1"><c>erlang:term_to_binary/1</c></seealso> and - <seealso marker="#enif_binary_to_term"><c>enif_binary_to_term</c></seealso>. - </p> + + <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"> + <c>erl_drv_thread_opts_create</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_thread_opts_destroy</c></seealso>.</p> + </desc> + </func> + + <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"> + <c>erl_drv_thread_self</c></seealso>.</p> + </desc> + </func> + + <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 + indicates a scheduler thread while a negative value or zero indicates + another type of thread. Currently the following specific types exist + (which may be extended in the future):</p> + <taglist> + <tag><c>ERL_NIF_THR_UNDEFINED</c></tag> + <item><p>Undefined thread that is not a scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_NORMAL_SCHEDULER</c></tag> + <item><p>A normal scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_DIRTY_CPU_SCHEDULER</c></tag> + <item><p>A dirty CPU scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_DIRTY_IO_SCHEDULER</c></tag> + <item><p>A dirty I/O scheduler thread.</p></item> + </taglist> + </desc> + </func> + + <func> + <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> + <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><c>time_unit</c> is the time unit of the returned value.</p> + <p>Returns <c>ERL_NIF_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 <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and + <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>.</p> + </desc> + </func> + + <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_get"> + <c>erl_drv_tsd_get</c></seealso>.</p> + </desc> + </func> + + <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_create"> + <c>erl_drv_tsd_key_create</c></seealso>.</p> </desc> + </func> + + <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_key_destroy"> + <c>erl_drv_tsd_key_destroy</c></seealso>.</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> - <fsummary></fsummary> - <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> - <fsummary></fsummary> - <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> - <fsummary></fsummary> - <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> - <fsummary></fsummary> - <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> - <fsummary></fsummary> - <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> - <fsummary></fsummary> - <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> - <fsummary>Determine type of current thread</fsummary> - <desc> - <p>Determine the type of currently executing thread. A positive value - indicates a scheduler thread while a negative value or zero indicates - another type of thread. Currently the following specific types exist - (which may be extended in the future):</p> - <taglist> - <tag><c>ERL_NIF_THR_UNDEFINED</c></tag> - <item><p>Undefined thread that is not a scheduler thread.</p></item> - <tag><c>ERL_NIF_THR_NORMAL_SCHEDULER</c></tag> - <item><p>A normal scheduler thread.</p></item> - <tag><c>ERL_NIF_THR_DIRTY_CPU_SCHEDULER</c></tag> - <item><p>A dirty CPU scheduler thread.</p></item> - <tag><c>ERL_NIF_THR_DIRTY_IO_SCHEDULER</c></tag> - <item><p>A dirty I/O scheduler thread.</p></item> - </taglist> - </desc> - </func> - <func> - <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> - <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_NIF_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: - <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> and - <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>. - </p> - </desc> - </func> - - <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_create">erl_drv_tsd_key_create</seealso>. - </p></desc> - </func> - <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_key_destroy">erl_drv_tsd_key_destroy</seealso>. - </p></desc> - </func> - <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_get">erl_drv_tsd_get</seealso>. - </p></desc> - </func> - <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> + + <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"> + <c>erl_drv_tsd_set</c></seealso>.</p> + </desc> </func> </funcs> + <section> - <title>SEE ALSO</title> - <p><seealso marker="erlang#load_nif-2">erlang:load_nif/2</seealso></p> + <title>See Also</title> + <p><seealso marker="erlang#load_nif-2"> + <c>erlang:load_nif/2</c></seealso></p> </section> </cref> |