spawn without linking?

Sean Hinde <>
Mon Apr 26 23:23:15 CEST 2004


On 26 Apr 2004, at 13:56, Joe Armstrong wrote:

> On Thu, 22 Apr 2004, Sean Hinde wrote:
>
>>
>> On 21 Apr 2004, at 04:20, Shawn Pearce wrote:
>>
>>> Actually, it is that hard to do...  the OTP behaviors offer lots
>>> of well tested/debugging implementations which handle the border
>>> cases extremely well.  Which a naive quick implementation using
>>> just the basic spawn_link/* and trap_exit won't get quite right on
>>> the first few tries.
>>>
>>> OTP rocks for that reason alone... but yea, gen_server isn't the
>>> most "Erlang" way to write a server, but its the Erlang/OTP way.
>>
>> How about this which I had fun writing today. It is almost Erlangish,
>> and it is something like OTP, and it is exactly Joe's selective 
>> receive
>> example. I can't decide whether it is ugly or profoundly beautiful.
>
> It is of course profoundly beautiful, but the syntax obscures the 
> beauty.

And isn't there a lot of it. Not for the faint hearted playing with 
this stuff, but it should be bread and butter.

>
> Just overload the LHS of !! so you can write
>
> 	[A,B,C] !! M
>
> This means send M to three processes (machines or whatever's) and
> gather three replies yielding [V1,V2,V3]

So, would this include monitor semantics by default?

And how could we make a timeout?

-define(IANALD, true).

case [A,B,C] !! M of
	[V1, V2, V3] ->
		success
	after 5000 ->
		exit(timeout)
	end,

Sean

>
> Cheers
>
> /Joe
>
>>
>> Sean
>>
>> %% Call a bunch of gen_servers with different requests in
>> %% parallel and return successes and failures. Any which
>> %% fail to answer within Timeout ms are included as failures.
>>
>> %% We require that the calling process will continue to ignore
>> %% late answers
>>
>> multi_call(Requests, Timeout) ->
>>      Mrefs = lists:map(
>>                fun({Name, Req}) ->
>>                        Mref = erlang:monitor(process, Name),
>>                        Name ! {'$gen_call', {self(), Mref}, Req},
>>                        {Name, Mref}
>>                end, Requests),
>>      get_results(Mrefs, [], [], Timeout, now()).
>>
>> get_results([{Name, Mref}|T], Succ, Fail, Timeout, Now_at_start) ->
>>      Timeout_val = max(Timeout - (timer:now_diff(now(), Now_at_start)
>> div 1000), 0),
>>      receive
>>          {Mref, Reply} ->
>>              erlang:demonitor(Mref),
>>              receive
>>                  {'DOWN', Mref, _, _, _} ->
>>                      get_results(T, [{Name, Reply}|Succ], Fail, 
>> Timeout,
>> Now_at_start)
>>              after 0 ->
>>                      get_results(T, [{Name, Reply}|Succ], Fail, 
>> Timeout,
>> Now_at_start)
>>              end;
>>          {'DOWN', Mref, _, _, _} ->
>>              get_results(T, Succ, [Name|Fail], Timeout, Now_at_start)
>>      after Timeout_val ->
>>              erlang:demonitor(Mref),
>>              get_results(T, Succ, [Name|Fail], Timeout, Now_at_start)
>>      end;
>> get_results([], Succ, Fail, _, _) ->
>>      {Succ, Fail}.
>>
>> max(A, B) when A >= B -> A;
>> max(A, B)             -> B.
>>
>




More information about the erlang-questions mailing list