NIF to wrap my multi-threaded C++ code
Asked Answered
R

1

6

I have a C++ code that implement a special protocol over the serial port. The code is multi-threaded and internally polls the serial port and do its own cyclic processing. I would like to call this driver from erlang and also receive events from this driver. My concern is that this C++ code is multi-threaded and also statefull meaning that when I call a certain function on the driver, it caches things internally which will be used/required on the subsequent calls of the driver. My questions are

1.Does NIF run in the same os process as the rest of my erlang proceses or NIF is launched in a separate os process?

2.Does it make sense to warp this multi-threaded stateful C++ code with NIF?

4.If NIF is not the right approach, what is the better way for me to make Elrang talk back and forth with this C++ code. I also prefer my C++ code to be inside the same OS process as the rest of my Erlang processes and as it looks like linked-in drivers are an option but not sure if the multi-threaded nature of my C++ code will be ok to that model. Plus I hear they can mess up elrang scheduler?

Reduplication answered 25/9, 2012 at 18:51 Comment(0)
T
4
  1. Unlike ports, NIFs are run within Erlang VM process, similar to drivers. Because of that, any NIF crashes will bring VM down as well. And, answering in advance, to your last question, NIFs, like drivers, may block your scheduler.

  2. That depends on the functionality you are implementing by this C++ code. Due to the answer 1), you probably want to avoid concurrency in the C++ part, since it's a potential source of errors. It's not always possible, of course. But if you are implementing, say, some workers pool, go ahead and implement 1-threaded code, spawning it as many times as you need.

  3. Drivers can be multi-threaded too, with same potential problems and quite similar performance (well, still slightly faster than NIFs). If you are not completely sure about your C++ code stability, use it as an Erlang port.

Speaking of the difference between NIFs and drivers, the former is synchronous natively, and the latter can be asynchronous (which can be really a huge advantage if you don't want to receive any answers for most of the commands). Drivers are easier to mess up and harder to implement (but once you grasp the main patterns and problems, they seem okay, actually).

Here's a good start for drivers: http://www.erlang.org/doc/apps/erts/driver.html

And something similar (behold the difference in complexity) for NIFs: http://www.erlang.org/doc/tutorial/nif.html

Thant answered 25/9, 2012 at 22:50 Comment(4)
Thank you for the answer. The thing is that I can not change the C++ code and it internally creates some limited threads. Plus it has locks over some its internal data structures where the nif calls will may to access and so the nif call may block until the internal thread releases the lock. Is that still ok assuming the c++ code is bug free? Also, it looks to me that all the Erlang processes run on only one thread (I only have one core) only and the vm does not use any thread pool? Is this right? If so how do we get concurrency in Erlang as we never know how long each erlang process can take?Reduplication
If you want to get the async behaviour you talk about you should use erlang.org/doc/man/erl_nif.html#enif_thread_create to create a thread which you then execute your C++ code in. The you use a pipe or somesuch to communicate with that thread and use enif_send_term to send back results. Implementing a driver might suite you better as you then can use the built in erlang async thread pool to do you C++ operations. Drivers also tend to be more flexible when running in a non-smp emulator (not same thing as smp:1:1).Acidophil
The number of threads in Erlang doesn't affect concurrency much. VM scheduler just loads the CPU time between all the processes (according to their priority, which is normal by default and which you can set for every process explicitly). You can get a better idea of what Erlang processes are from here: c2.com/cgi/wiki?GreenVsNativeThreadsThant
Normally you are not allowed to block or wait during NIF calls, but Erlang R17 introduces "dirty io schedulers" that allow this. In a nutshell, the VM will run your NIF in a separate thread so that scheduler threads will not be affected by your blocking/waiting.Bushhammer

© 2022 - 2024 — McMap. All rights reserved.