[erlang-questions] Static callback in NIF
Wed Jun 29 23:51:46 CEST 2016
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