<div dir="ltr">Static vs priv_data are functionally the same here so it doesn't matter which way you go.  I can empathize with your sense of dread; there are a lot of rules to keep track of for keeping Undefined Behavior at bay.  But you seem to have a good handle on things.<br><br><div class="gmail_quote"><div dir="ltr">On Thu, Jun 30, 2016 at 6:02 AM Igor Clark <<a href="mailto:igor.clark@gmail.com">igor.clark@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi folks,<br>
<br>
I've got a NIF that uses some library code to talk to specific hardware.<br>
It's a hobby project with only one user (me) and no real performance<br>
concerns, so what I've got works well at the moment, but I think I'm<br>
doing some sneaky/dirty stuff and would like to know the best way to do<br>
what I need.<br>
<br>
Sending messages outwards from erlang->C->HW is easy, very quick, and<br>
works fine. I return a pointer to the HW reference back to erlang using<br>
the enif_*_resource functions, and manage keeping track of everything on<br>
the erlang side, which feels pretty natural.<br>
<br>
Coming the other way works fine too, but relies on a C function callback<br>
which gets called when the hardware has a message for me. Right now I<br>
just have a static function in the NIF C code which I pass to the<br>
library. I create a static ErlNifEnv on NIF load() which I keep around<br>
and use in the callback to send messages to a specified erlang Pid,<br>
passed in via enif_get_local_pid() in another NIF function and also<br>
stored statically. This works a treat, but I'm feeling some pretty<br>
strong dread that it's very much the wrong way to do things, and asking<br>
for scheduler headaches/explosions.<br>
<br>
I'm planning to try storing the various resources in priv_data at load()<br>
time, on the theory that that way the memory would at least be managed<br>
by the NIF system rather than just as enif_alloc()'ing static pointers,<br>
but I'm not sure if that would make any diffrence if code external to<br>
the scheduler calls back into it.<br>
<br>
I've looked into running this part as a C node or a port that sends<br>
messages with the HW data in a callback in its own process, and the<br>
communication seems straightforward enough, but it also seems like I<br>
immediately need to start designing mechanisms to deal with working out<br>
where to send received messages, almost a protocol in itself. Whereas<br>
with the NIF+callback method I have a lot of the work done for me -<br>
except, of course, for the synchronisation and memory management, which<br>
is the bit I'm worried about.<br>
<br>
FWIW the callback code doesn't modify any of the static data structures<br>
directly, it just calls library code which uses the stored references to<br>
work out which hardware device & channel to send the message to.<br>
<br>
What's the best practice here? Is a callback in a NIF OK if it's stored<br>
in priv_data, or is it never OK? What's the best way to do this if not?<br>
<br>
Would appreciate any tips!<br>
<br>
Cheers,<br>
Igor<br>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div></div>