[erlang-questions] Static callback in NIF

Igor Clark igor.clark@REDACTED
Wed Jun 29 23:51:46 CEST 2016

Hi folks,

I've got a NIF that uses some library code to talk to specific hardware. 
It's a hobby project with only one user (me) and no real performance 
concerns, so what I've got works well at the moment, but I think I'm 
doing some sneaky/dirty stuff and would like to know the best way to do 
what I need.

Sending messages outwards from erlang->C->HW is easy, very quick, and 
works fine. I return a pointer to the HW reference back to erlang using 
the enif_*_resource functions, and manage keeping track of everything on 
the erlang side, which feels pretty natural.

Coming the other way works fine too, but relies on a C function callback 
which gets called when the hardware has a message for me. Right now I 
just have a static function in the NIF C code which I pass to the 
library. I create a static ErlNifEnv on NIF load() which I keep around 
and use in the callback to send messages to a specified erlang Pid, 
passed in via enif_get_local_pid() in another NIF function and also 
stored statically. This works a treat, but I'm feeling some pretty 
strong dread that it's very much the wrong way to do things, and asking 
for scheduler headaches/explosions.

I'm planning to try storing the various resources in priv_data at load() 
time, on the theory that that way the memory would at least be managed 
by the NIF system rather than just as enif_alloc()'ing static pointers, 
but I'm not sure if that would make any diffrence if code external to 
the scheduler calls back into it.

I've looked into running this part as a C node or a port that sends 
messages with the HW data in a callback in its own process, and the 
communication seems straightforward enough, but it also seems like I 
immediately need to start designing mechanisms to deal with working out 
where to send received messages, almost a protocol in itself. Whereas 
with the NIF+callback method I have a lot of the work done for me - 
except, of course, for the synchronisation and memory management, which 
is the bit I'm worried about.

FWIW the callback code doesn't modify any of the static data structures 
directly, it just calls library code which uses the stored references to 
work out which hardware device & channel to send the message to.

What's the best practice here? Is a callback in a NIF OK if it's stored 
in priv_data, or is it never OK? What's the best way to do this if not?

Would appreciate any tips!


More information about the erlang-questions mailing list