multiple waiting gen_tcp:accepts

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

multiple waiting gen_tcp:accepts

Willem Broekema
Is there a reason why there can not be two waiting gen_tcp:accept()'s at
the same time? In the code below,  when "start()" is called, the
*second* spawned do_accept will write "{error, einval}" as soon as it is
started, while I would expect this to behave as:

- A1 and A2 are put in a queue waiting for incoming connections
- A1 gets the first incoming one
- A2 gets the second

start() ->
    {ok, LSock} = gen_tcp:listen(5568,
         [binary, {packet, 0}, {active, true}, {reuseaddr, true}]),
    A1 = spawn_link(?MODULE, do_accept, [LSock, 1]),
    A2 = spawn_link(?MODULE, do_accept, [LSock, 2]),
    ready.

do_accept(LSock, N) ->
    io:write( gen_tcp:accept(LSock) ).


Another question:

"get_func()" below returns a function. Immediatly calling
"get_func()(3)" gives a syntax error, while "A = get_func(), A(3)"
behaves ok. What's the reason for that? I guess it has to do with that
funs are a late addition to Erlang, and the syntax parser didn't have to
deal with double brackets - "...(..)(..)" - before that?

triple(X) -> 3*X.

get_func() ->
    fun triple/1.

exec_func() ->
    %% this gives an error:
    % get_func()(3).

    %% while this works:
    A = get_func(),
    A(3).


TIA

- Willem



Reply | Threaded
Open this post in threaded view
|

multiple waiting gen_tcp:accepts

Tony Rogvall-3
Willem Broekema wrote:

> Is there a reason why there can not be two waiting gen_tcp:accept()'s
> at the same time? In the code below,  when "start()" is called, the
> *second* spawned do_accept will write "{error, einval}" as soon as it
> is started, while I would expect this to behave as:

The simple answer is that the driver (erlang-c interface) is not coded
to handle multiple accepts on the the same listen socket. Of course this
should be possible, but first there must be yet an other iteration over
the inet_drv implementation. The next inet_drv/gen_tcp implementation
will hopefully handle this.

The more complicated answer is that the problem is that with
non-blocking IO you have to listen/poll on the listen file descriptor to
see when you can do the accept without blocking the entire erlang node.
This means that the inet_drv driver must handle the accept queue it
self, and this is what is missing (or the queue length is max 1).

>
> - A1 and A2 are put in a queue waiting for incoming connections
> - A1 gets the first incoming one
> - A2 gets the second
>
> start() ->
>    {ok, LSock} = gen_tcp:listen(5568,
>         [binary, {packet, 0}, {active, true}, {reuseaddr, true}]),
>    A1 = spawn_link(?MODULE, do_accept, [LSock, 1]),
>    A2 = spawn_link(?MODULE, do_accept, [LSock, 2]),
>    ready.

I would not bet on A1 getting the first and A2 getting the second, but
may be it does not make any difference in this case ?

>
> do_accept(LSock, N) ->
>    io:write( gen_tcp:accept(LSock) ).
>
>
> Another question:
>
> "get_func()" below returns a function. Immediatly calling
> "get_func()(3)" gives a syntax error, while "A = get_func(), A(3)"
> behaves ok. What's the reason for that? I guess it has to do with that
> funs are a late addition to Erlang, and the syntax parser didn't have
> to deal with double brackets - "...(..)(..)" - before that?
>
> triple(X) -> 3*X.
>
> get_func() ->
>    fun triple/1.
>
> exec_func() ->
>    %% this gives an error:

Try this:
        (get_func())(3).

>
>    % get_func()(3).
>
>    %% while this works:
>    A = get_func(),
>    A(3).
>
>
> TIA
>
> - Willem

/Tony





Reply | Threaded
Open this post in threaded view
|

multiple waiting gen_tcp:accepts

Matthias Lang-2
In reply to this post by Willem Broekema

 > "get_func()" below returns a function. Immediatly calling
 > "get_func()(3)" gives a syntax error, while "A = get_func(), A(3)"
 > behaves ok. What's the reason for that? I guess it has to do with that
 > funs are a late addition to Erlang, and the syntax parser didn't have to
 > deal with double brackets - "...(..)(..)" - before that?

The grammar (see E2 in
http://www.erlang.org/download/erl_spec47.ps.gz) does allow

  (get_func())(3)

so at least the grammar agrees with reality. As to why it's that way,
I don't know. Maybe it's a bit like asking 'why isn't there any
currying'. There just isn't.

Matthias