Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure all relevant erl_nif functionality is represented in some way #44

Open
hansihe opened this issue Dec 31, 2016 · 10 comments
Open

Comments

@hansihe
Copy link
Member

hansihe commented Dec 31, 2016

If there is anything in particular you need, please comment below and we can work something out.

Primitives

Primitives are fully supported through Encoder.

  • enif_get_double()
  • enif_get_int()
  • enif_get_int64()
  • enif_get_long()
  • enif_get_uint()
  • enif_get_uint64()
  • enif_get_ulong()
  • enif_make_double()
  • enif_make_int64()
  • enif_make_long()
  • enif_make_int()
  • enif_make_uint()
  • enif_make_uint64()
  • enif_make_ulong()

Atoms

  • enif_get_atom()
  • enif_get_atom_length() Will add if anyone has a legitimate use.
  • enif_make_existing_atom() N/A
  • enif_make_existing_atom_len()
  • enif_make_atom() N/A
  • enif_make_atom_len()

Lists

  • enif_make_reverse_list() NifTerm::list_reverse()
  • enif_get_list_cell() NifTerm::list_get_cell()
  • enif_get_list_length() NifTerm::list_length()
  • enif_make_list()
  • enif_make_list_from_array()
  • enif_make_list_cell()
  • enif_make_string_len()

Char lists

  • enif_make_string()
  • enif_get_string()

Maps

  • enif_get_map_size()
  • enif_get_map_value()
  • enif_make_map_put()
  • enif_make_map_remove()
  • enif_make_map_update()
  • enif_map_iterator_create()
  • enif_map_iterator_get_pair()
  • enif_map_iterator_is_head()
  • enif_map_iterator_is_tail()
  • enif_map_iterator_next()
  • enif_map_iterator_prev()
  • enif_map_iterator_destroy()
  • enif_make_new_map()

Binaries

Supported through binary abstraction.

  • enif_alloc_binary()
  • enif_realloc_binary()
  • enif_inspect_binary()
  • enif_inspect_iolist_as_binary()
  • enif_make_new_binary()
  • enif_release_binary()
  • enif_make_binary()
  • enif_make_sub_binary()

Tuples

  • enif_get_tuple()
  • enif_make_tuple_from_array()
  • enif_make_tuple() N/A

Resources

Exposed through resource abstraction.

  • enif_keep_resource()
  • enif_get_resource()
  • enif_sizeof_resource()
  • enif_release_resource()
  • enif_alloc_resource()
  • enif_make_resource()
  • enif_open_resource_type()
  • enif_make_resource_binary()

Misc terms

  • enif_make_pid()
  • enif_make_ref()
  • enif_get_local_pid()
  • enif_get_local_port()

Term utils

  • enif_make_copy()
  • enif_term_to_binary()
  • enif_binary_to_term()
  • enif_compare()
  • enif_is_identical()
  • enif_snprintf()
  • enif_port_command()
  • enif_is_port_alive()
  • enif_is_process_alive()

Type tests

Exposed as methods on NifTerm.

  • enif_is_atom()
  • enif_is_binary()
  • enif_is_list()
  • enif_is_pid()
  • enif_is_port()
  • enif_is_ref()
  • enif_is_tuple()
  • enif_is_empty_list()
  • enif_is_exception()
  • enif_is_fun()
  • enif_is_map()
  • enif_is_number()

Scheduling

  • enif_consume_timeslice()
  • enif_schedule_nif() See this

Exceptions

  • enif_has_pending_exception() Useless for us since we don't expose raise_exception to the user.

Supported through rustler::Error. It is undesirable to expose these directly:

  • enif_make_badarg()
  • enif_raise_exception()

Env

  • enif_free_env()
  • enif_clear_env()
  • enif_alloc_env()
  • enif_self()
  • enif_send() See this

Time

  • enif_cpu_time()
  • enif_now_time()
  • enif_monotonic_time()
  • enif_time_offset()
  • enif_convert_time_unit()

Misc

  • enif_getenv()
  • enif_alloc() N/A
  • enif_free() N/A
  • enif_priv_data() No plans to support.
  • enif_system_info()
  • enif_make_unique_integer()
  • enif_is_current_process_alive()

Threading

Rust has its own threading APIs. There are no plans to support this.

  • enif_rwlock_tryrlock()
  • enif_rwlock_tryrwlock()
  • enif_thread_create()
  • enif_thread_join()
  • enif_tsd_key_create()
  • enif_mutex_trylock()
  • enif_thread_type()
  • enif_equal_tids()
  • enif_cond_broadcast()
  • enif_cond_destroy()
  • enif_cond_signal()
  • enif_cond_wait()
  • enif_mutex_destroy()
  • enif_mutex_lock()
  • enif_mutex_unlock()
  • enif_rwlock_destroy()
  • enif_rwlock_rlock()
  • enif_rwlock_runlock()
  • enif_rwlock_rwlock()
  • enif_rwlock_rwunlock()
  • enif_thread_exit()
  • enif_thread_opts_destroy()
  • enif_tsd_key_destroy()
  • enif_tsd_set()
  • enif_tsd_get()
  • enif_cond_create()
  • enif_mutex_create()
  • enif_rwlock_create()
  • enif_thread_opts_create()
  • enif_thread_self()
@hansihe hansihe changed the title Make sure all erl_nif functionality is represented in some way Make sure all relevant erl_nif functionality is represented in some way Dec 31, 2016
@hansihe
Copy link
Member Author

hansihe commented Jan 1, 2017

Problems

  • enif_send(): Documentation requires calling env to be passed when called within a NIF call. There is no way to enforce this at compile-time.
  • enif_schedule_nif(): Requires return value to be returned from the NIF call. There is no straightforward way to enforce this at compile-time.

Probably going to put these features under a cargo feature since they require additional caution from the user.

We might want to open an issue on OTP about these problems?

@jorendorff
Copy link
Collaborator

For enif_send(), we can just always require an env. I'm not sure what kind of situation would lead a user to want to send a message without having an env handy.

@hansihe
Copy link
Member Author

hansihe commented Jan 10, 2017

@jorendorff The erl_nif docs say: "env: The environment of the calling process. Must be NULL only if calling from a created thread"

This means that by not supplying an env when doing send from within a NIF call, we are technically breaking an API invariant.

@jorendorff
Copy link
Collaborator

@hansihe We always supply an env, so I think we're OK.

@hansihe
Copy link
Member Author

hansihe commented Jan 11, 2017

@jorendorff Just checked the current implementation. It is wrong.

The docs say the first env should be the env of the calling process if called from a nif, null if and only if from a calling thread. The second env should be the env the message term belongs to.

The message term env is never supposed to be passed as the first argument.

@jorendorff
Copy link
Collaborator

You're right. We could fix it using thread-local storage; I don't see any other way.

@hansihe
Copy link
Member Author

hansihe commented Jan 11, 2017

I checked the source a little while ago. They don't use the first env for anything other than to improve tracing functionality.

So, passing null always is fine with the current BEAM implementation. The question is if we want to take that risk, it might change in the future.

@jorendorff
Copy link
Collaborator

It seems best to code to the documented API. I'll patch it.

@hansihe hansihe added this to the 1.0 milestone Jan 19, 2017
@filmor
Copy link
Member

filmor commented Sep 19, 2019

This API list hasn't been updated for quite a while and is missing all NIF API functions for OTP>=20.

@evnu
Copy link
Member

evnu commented Feb 18, 2020

I wrote a small helper to find all documented NIF functions. The escript allows filtering by version prefix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants