From e606eae1325a9f73140ab309d5dbbb7cdb589a04 Mon Sep 17 00:00:00 2001 From: Ted Burghart Date: Mon, 22 May 2017 15:36:09 -0400 Subject: Add enif_whereis_...() functions #### Why do we need this new feature? There are cases when a NIF needs to send a message, using `enif_send()`, to a long-lived process with a registered name. A common use-case is logging, where asynchronous fire-and-forget messages are the norm. There can also be cases where a yielding or dirty NIF or background thread may request a callback from a service with additional information it needs to complete its operation, yielding or waiting (with suitable timeouts, etc) until its state has been updated through the NIF module's API. NIFs can only send messages to pids, and the lack of name resolution leaves a complicated dance between separate monitoring processes and the NIF as the only way to keep a NIF informed of the whereabouts of such long-lived processes. Providing a reliable, built-in facility for NIFs to resolve process (or port) names simplifies these use cases considerably. #### Risks or uncertain artifacts? Testing has not exposed any significant risk. The implementation behaves as expected on regular and dirty scheduler threads as well as non-scheduler threads. By constraining the `enif_whereis_...()` functions to their minimal scopes and using patterns consistent with related functions, the implementation, testing, and maintenance burden is low. The API and behavior of existing functions is unchanged. #### How did you solve it? While extending `enif_send()` to operate on a pid or an atom (as `erlang:send/2` does) was attractive, it would have entailed changing the type of its `to_pid` parameter and thereby breaking backward compatibility. The same consideration applies to `enif_port_command()`. That leaves a choice between 1, 2, or 3 new functions: 1. `enif_whereis()` 2. `enif_whereis_pid()` and `enif_whereis_port()` 3. All of the above. While option (1), directly mimicking the behavior of `erlang:whereis/1`, is appealing, it poses potential problems if `pid()` or `port()` are subsequently implemented as non-integral types that must be bound to an owning `ErlNifEnv` instance. Therefore, option (2) has been chosen to use `ErlNifPid`/`ErlNifPort` structures in the API to maintain proper term ownership semantics. --- erts/doc/src/erl_nif.xml | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (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 3eb3e04f33..5a69bed34c 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -3002,6 +3002,63 @@ if (retval & ERL_NIF_SELECT_STOP_CALLED) { erl_drv_tsd_set.

+ + + int + enif_whereis_pid(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPid *pid) + Looks up a process by its registered name. + +

Looks up a process by its registered name.

+ + env + The environment of the calling process. Must be NULL + only if calling from a created thread. + name + The name of a registered process, as an atom. + *pid + The ErlNifPid + in which the resolved process id is stored. + +

On success, sets *pid to the local process registered with + name and returns true. If name is not a + registered process, or is not an atom, false is returned and + *pid is unchanged.

+

Works as + erlang:whereis/1, but restricted to processes. See + enif_whereis_port + to resolve registered ports.

+
+
+ + + int + enif_whereis_port(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPort *port) + Looks up a port by its registered name. + +

Looks up a port by its registered name.

+ + env + The environment of the calling process. Must be NULL + only if calling from a created thread. + name + The name of a registered port, as an atom. + *port + The ErlNifPort + in which the resolved port id is stored. + +

On success, sets *port to the port registered with + name and returns true. If name is not a + registered port, or is not an atom, false is returned and + *port is unchanged.

+

Works as + erlang:whereis/1, but restricted to ports. See + enif_whereis_pid + to resolve registered processes.

+
+
+
-- cgit v1.2.3