[erlang-questions] gen_tcp nonblocking send

Per Hedeland per@REDACTED
Thu May 1 21:22:20 CEST 2008


"Valentin Micic" <valentin@REDACTED> wrote:
>
>As you've said -- it is a workaround. Consider that under some circumstances 
>such workaround may cause problems -- think of it this way: You're not 
>really solving the problem, just shifting it elsewhere.

But that was precisely what he *wanted*: the possibility to note the
problem and deal with it "elsewhere" (i.e. his sender will maintain its
own queue and eliminate useless data there).

>Under normal circumstances (as you've outlined), if sender and receiver are 
>not in some kind of "synchronous" engagement, in other words, if your next 
>send does not depend on receiving something from a remote peer; and you have 
>a "sluggish" remote receiver, your process would block once local buffer is 
>full. If you change this by introducing intermediate server, as suggested --  
>call it a REALY; you are not changing the fact that this RELAY will block 
>when local sending buffer gets full. However, as the sending process is now 
>sending "normal" Erlang messages, it will have no way of figuring out that 
>RELAY's buffer is full, thus, it will keep sending, eventually clogging 
>RELAY's process message queue.

You didn't read my suggestion carefully enough - try again.

>OTOH, if one assumes that O_NDELAY would return immediately once the local 
>buffer is full, this would help solving the problem you're referring to, by 
>allowing a programmer to find the most suitable solution to a given 
>problem - anything from immediate disconnection/reconnection to some form of 
>internal buffering (which, mind you, cost only in terms of memory, and not 
>so much in CPU cycles).

IMO, exposing O_NDELAY/O_NONBLOCK at the Erlang level would be a huge
mistake. Networking (and many other "interactions with the environment")
is so simple in Erlang because it just hides all the gory details that
you get immediately thrown in your face when using a C interface to the
same functionality. And when you really need some functionality provided
by the gory-details interface but not by the Erlang counterpart, there's
often a nice Erlangish way to achieve it, that just wouldn't be possible
at the gory-details and/or C level.

This case is an excellent illustration of that - in Erlang, you don't
want a send() that says "sorry, I only managed to send N bytes of your
complex nested list/binary structure, you need to re-send the rest" -
but you might want a send() that doesn't block, but just sends you a
message when it's done. Which is exactly what my "relay" process
suggestion implements, and which *could* be provided as a standard
gen_tcp(3) API function - but it's probably an uncommon enough need that
doing that isn't motivated.

--Per



More information about the erlang-questions mailing list