[erlang-questions] Static callback in NIF

Igor Clark igor.clark@REDACTED
Fri Jul 1 19:38:03 CEST 2016


Hi Sverker, thanks.

I'm only using enif_alloc_env() to create the static ErlNifEnv, in the 
NIF load(). I haven't had compiler warnings about it - certainly haven't 
noticed any, and just did a clean+build to check.

(I'm using the rebar3 port compiler on erlang 18.3, erts-7.3 on OSX 
10.11.5. It doesn't seem to show warnings without errors, and I can't 
find a verbose mode - so I used 'rebar comp --verbose' to inspect 'cc' 
lines and warnings, and there's nothing there about the static 
ErlNifEnv, either.)

I haven't been doing any digging in erts headers, as I'd be pretty 
nervous about doing anything undocumented :-)

Am I missing something?

Cheers,

Igor


On 01/07/2016 08:18, Sverker Eriksson wrote:
> The only legit way to create an ErlNifEnv is to call enif_alloc_env().
>
> I bet the compiler warned about your static ErlNifEnv
> just before you went hunting for erts internal header files :-)
>
> In OTP-19.0 the 'msg_env' argument to enif_send() can be NULL
> in which case the message will be copied and you can reuse
> the environment for the next message with enif_clear_env().
> This is effective if the message is small.
>
> /Sverker, Erlang/OTP
>
>
> On 06/30/2016 08:31 PM, Igor Clark wrote:
>> Thanks Daniel, good to hear.
>>
>> Thanks also Roger & Sergej for your replies. I'll try out 
>> enif_alloc_env()'ing a new ErlNifEnv each time the callback uses 
>> enif_send(), rather than just leaving it static.
>>
>> Cheers!
>>
>> Igor
>>
>> On 30/06/2016 07:45, Daniel Goertzen wrote:
>>> 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.
>>>
>>> On Thu, Jun 30, 2016 at 6:02 AM Igor Clark <igor.clark@REDACTED 
>>> <mailto:igor.clark@REDACTED>> wrote:
>>>
>>>     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!
>>>
>>>     Cheers,
>>>     Igor
>>>     _______________________________________________
>>>     erlang-questions mailing list
>>> erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20160701/066a68f0/attachment.htm>


More information about the erlang-questions mailing list