From e9845ee002fdd6995ec1a097993a0e7e145c6488 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 21 Nov 2018 18:33:01 +0100 Subject: erts: Clarify erl_nif docs about callback environments --- erts/doc/src/erl_nif.xml | 67 +++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 24 deletions(-) (limited to 'erts/doc/src/erl_nif.xml') diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 190ec12d0e..095fc79bdf 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -293,7 +293,7 @@ return term; arguments. When you write to a shared state either through static variables or enif_priv_data, you need to supply your own explicit - synchronization. This includes terms in process-independent + synchronization. This includes terms in process independent environments that are shared between threads. Resource objects also require synchronization if you treat them as mutable.

The library initialization callbacks load and @@ -596,7 +596,7 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, --enable-static-nifs, you must define STATIC_ERLANG_NIF before the ERL_NIF_INIT declaration.

- int (*load)(ErlNifEnv* env, void** priv_data, + int (*load)(ErlNifEnv* caller_env, void** priv_data, ERL_NIF_TERM load_info)

load is called when the NIF library is loaded @@ -612,7 +612,7 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, anything other than 0. load can be NULL if initialization is not needed.

- int (*upgrade)(ErlNifEnv* env, void** + int (*upgrade)(ErlNifEnv* caller_env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)

upgrade is called when the NIF library is loaded @@ -626,7 +626,7 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,

The library fails to load if upgrade returns anything other than 0 or if upgrade is NULL.

- void (*unload)(ErlNifEnv* env, void* + void (*unload)(ErlNifEnv* caller_env, void* priv_data)

unload is called when the module code that @@ -654,27 +654,41 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,

ErlNifEnv represents an environment that can host Erlang terms. All terms in an environment are valid as long as the environment is valid. ErlNifEnv is an opaque type; pointers to - it can only be passed on to API functions. Two types of environments + it can only be passed on to API functions. Three types of environments exist:

- Process-bound environment + Process bound environment

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.

-

A process-bound environment contains transient information +

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.

+ process bound environments between NIF calls.

- Process-independent environment + Callback environment + +

Passed as the first argument to all the non-NIF callback functions + (load, + upgrade, + unload, + dtor, + down and + stop). + Works like a process bound environment but with a temporary + pseudo process that "terminates" when the callback has + returned. Terms may be created in this environment but they will + only be accessible during the callback.

+
+ Process independent environment

Created by calling enif_alloc_env. This environment can be used to store terms between NIF calls and to send terms with enif_send. A - process-independent environment with all its terms is valid until + process independent environment with all its terms is valid until you explicitly invalidate it with enif_free_env or enif_send.

@@ -799,7 +813,7 @@ typedef struct { ErlNifResourceDtor -typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); +typedef void ErlNifResourceDtor(ErlNifEnv* caller_env, void* obj);

The function prototype of a resource destructor function.

The obj argument is a pointer to the resource. The only allowed use for the resource in the destructor is to access its @@ -809,7 +823,7 @@ typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); ErlNifResourceDown -typedef void ErlNifResourceDown(ErlNifEnv* env, void* obj, ErlNifPid* pid, ErlNifMonitor* mon); +typedef void ErlNifResourceDown(ErlNifEnv* caller_env, void* obj, ErlNifPid* pid, ErlNifMonitor* mon);

The function prototype of a resource down function, called on the behalf of enif_monitor_process. obj is the resource, pid @@ -820,7 +834,7 @@ typedef void ErlNifResourceDown(ErlNifEnv* env, void* obj, ErlNifPid* pid, ErlNi ErlNifResourceStop -typedef void ErlNifResourceStop(ErlNifEnv* env, void* obj, ErlNifEvent event, int is_direct_call); +typedef void ErlNifResourceStop(ErlNifEnv* caller_env, void* obj, ErlNifEvent event, int is_direct_call);

The function prototype of a resource stop function, called on the behalf of enif_select. obj is the resource, event is OS event, @@ -987,7 +1001,7 @@ typedef struct { ErlNifEnv *enif_alloc_env() Create a new environment. -

Allocates a new process-independent environment. The environment can +

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 enif_make_copy or @@ -1211,14 +1225,17 @@ typedef struct { - intenif_demonitor_process(ErlNifEnv* env, void* obj, + intenif_demonitor_process(ErlNifEnv* caller_env, void* obj, const ErlNifMonitor* mon) Cancel a process monitor.

Cancels a monitor created earlier with enif_monitor_process. Argument obj is a pointer - to the resource holding the monitor and *mon identifies the monitor.

+ to the resource holding the monitor and *mon identifies the + monitor.

+

Argument caller_env is the environment of the calling process + or callback. Must only be NULL if calling from a custom thread.

Returns 0 if the monitor was successfully identified and removed. Returns a non-zero value if the monitor could not be identified, which means it was either

@@ -2572,7 +2589,7 @@ enif_map_iterator_destroy(env, &iter); - intenif_monitor_process(ErlNifEnv* env, void* obj, + intenif_monitor_process(ErlNifEnv* caller_env, void* obj, const ErlNifPid* target_pid, ErlNifMonitor* mon) Monitor a process from a resource. @@ -2593,6 +2610,8 @@ enif_map_iterator_destroy(env, &iter); enif_compare_monitors. A monitor is automatically removed when it triggers or when the resource is deallocated.

+

Argument caller_env is the environment of the calling process + or callback. Must only be NULL if calling from a custom thread.

Returns 0 on success, < 0 if no down callback is provided, and > 0 if the process is no longer alive.

This function is only thread-safe when the emulator with SMP support @@ -2768,7 +2787,7 @@ enif_map_iterator_destroy(env, &iter); The port ID of the receiving port. The port ID is to refer to a port on the local node. msg_env - The environment of the message term. Can be a process-independent + The environment of the message term. Can be a process independent environment allocated with enif_alloc_env or NULL. msg @@ -3124,26 +3143,26 @@ if (retval & ERL_NIF_SELECT_STOP_CALLED) {

Initializes the ErlNifPid variable at *pid to represent the calling process.

Returns pid if successful, or NULL if caller_env is not - a process-bound environment.

+ a process bound environment.

- intenif_send(ErlNifEnv* env, ErlNifPid* to_pid, + intenif_send(ErlNifEnv* caller_env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg) Send a message to a process.

Sends a message to a process.

- env - The environment of the calling process. Must be NULL - only if calling from a created thread. + caller_env + The environment of the calling process or callback. Must be NULL + only if calling from a custom thread not spawned by ERTS. *to_pid The pid of the receiving process. The pid is to refer to a process on the local node. msg_env The environment of the message term. Must be a - process-independent environment allocated with + process independent environment allocated with enif_alloc_env or NULL. msg -- cgit v1.2.3