Non-Blocking IO

Hi everyone,

I’m about to start a big project, a server application for a certain game, and i need to build a non-blocking IO functionality to listen connection and receive packets.

What should i know to build this functionallity? There is some lib that already do this ? There is some lib (ex: mongodb, redis) that implement this, so i can read and learn how to do ?

Thanks.

Are you speaking about non blocking keyboard IO or network? In general, despite of the kind of IO, if you wire up your processes correctly, there shouldn’t be a block, so at least in regard to this, it’s the same as in every language, but of course the way how the processes communicate to each other is different. To be more precise we need to have more details about the type of IO, then we can probably give hints on ready made packages or even elixir or erlang modules that are already there.

For networking gen_tcp and gen_udp come to my mind spontaniously

2 Likes

Check out https://hex.pm/packages/ranch, a wrapper around gen_tcp

1 Like

It depends a little on what you mean by block. The base system in the erlang ecosphere including elixir will never block the system even if you do a blocking operation like a synchronous read. At most the (elixir) process which does the blocking call will wait until a reply is received. In that sense it is perfectly acceptable to write code which blocks. You won’t ruin things for the rest of the system.

5 Likes

As long as that input is handled in a separate process, thats what I meant above by saying “if you wire up your processes correctly, there shouldn’t be a block”.

Yes, of course. Sorry, I am so environmentally challenged that I didn’t even consider not doing it in a separate process. :slight_smile:

5 Likes

Sorry, i didn’t specify. I’m talking about network.

1 Like

You don’t have to talking Blocking / Non-Blocking IO issues inside Elixir/Erlang VM.

  1. If you are running long task for I/O operation, it didn’t affect Erlang VM. Everything is still running.

  2. If you wants Put a Background Task and notify users later on, you just simply create a process to handle this issues. Erlang processes are really cheap. It don’t cost too memory.

If you are programming with Erlang/Elixir, you just simply follows the traditional way to programs. It doesn’t like the Node.js, Ruby, Python, etc.

1 Like

Here’s a quote from Elixir in Action about how I/O calls are handled internally. For context this discussion happens in a section about how the BEAM preempts processes for scheduling:

Another important case of implicit yielding involves I/O operations, which are internally executed on separate threads called async threads. When issuing an I/O call, the calling process is preempted, and other processes get the execution slot. After the I/O operation finishes, the scheduler resumes the calling process. A great benefit of this is that your I/O code looks synchronous, while under the hood it still runs asynchronously. By default, BEAM fires up 10 async threads, but you can change this via the +A n Erlang flag.

So you kind of get this for free in Elixir.

6 Likes

Yup, there has been a lot work put into the BEAM and the OTP system on top of it to make sure things don’t block. It has always been a fundamental requirement that the system should never block.

“Blocking is bad, m’kay. You shouldn’t do blocking. If you do them, you’re bad, because blocking is bad, m’kay.”

7 Likes