defining behaviours (Re: Design Patterns for Erlang)

Ulf Wiger <>
Mon Feb 19 17:00:32 CET 2001


On Mon, 19 Feb 2001, Martin Bjorklund wrote:

>Ulf Wiger <> wrote:
>
>> I'm currently looking at how behaviours are defined.
>> Personally, I don't like the idea of poking into otp_internal.erl
>> in order to define a new behaviour. In practice, this means that 
>> users of OTP can't define their own patterns.
>
>I wouldn't go that far - of course users can define new behaviours;
>you don't have to modify otp_internal.erl at all.  The only function
>provided by otp_internal is that the compiler checks exported
>functions, and warns if a function required by the behaviour is
>missing. A behaviour is of course much more than this...

Hmm, yes, I'll grant you that. What I meant was that when people
define their own behaviours, they want to be able to enforce these
checks as well... and others. There should perhaps be a good way to
add your own functionality to the linter.


>> behaviour_info(exports) ->
>>   [{init, 1}, {handle_call, 3}, {handle_cast, 2}, {handle_info, 2},
>>    {terminate, 2}, {code_change, 3}];
>> behaviour_info(_) ->
>>   [].
>
>But I think it should be a bit more detailed, specifically we should
>make a distiction between mandatory and optional functions:
>
>
>-module(gen_server).
>...
>-export([behaviour_info/1]).
>
>behaviour_info(mandatory_exports) ->
>  [{init, 1}, {terminate, 2}];
>behaviour_info(optional_exports) ->
>  [{handle_call, 3}, {handle_cast, 2}, {handle_info, 2},
>   {code_change, 3}];
>behaviour_info(_) ->
>  [].


Good idea.


>> Furthermore, I'd like to introduce the following requirement:
>> 
>> - A behaviour which wants a process must implement a function
>>   B:init_it/6, with the following arguments:
>
>Comments below.
>
>> Why do this?
>> 
>> Because I want to be able tell a supervisor to start a generic
>> server, or other behaviour, and have the supervisor take care of 
>> actually starting the process.
>
>What do you mean - the supervisor starts the process already...?


Erm, not exactly. The function that spawns the process does execute in
the supervisor process, but the supervisor has no control over it: it
simply calls an opaque function which (presumably) calls some version
of spawn, and returns a pid.

What I meant was that the supervisor should be given a specification
and _specifically_ start the process.



>> Three immediate advantages come to 
>> mind:
>> 
>> - The supervisor can make sure that the process is started with 
>>   spawn_link(); Today, if a gen_server is started with e.g. 
>>   gen_server:start(), supervision will be ineffective (no link.)
>
>The supervisor could call link() explicitly to acheive this effect.
>We had endless discussions about this when we implemented this...
>It's not safe anyway, since the process could call unlink() when it's
>started.

Yes, but there's a distinct difference between e.g. calling
gen_server:start() instead of gen_server:start_link() because you
didn't know any better, and explicitly unlinking from the supervisor,
which is really a form of sabotage.

>monitor is not a good idea either, since the child wants to
>be notified if the supervisor dies.  We agreed that the supervision
>mechanism as it is today is for co-operating processes.

I'm thinking that the supervisor needs to use both: monitor in order
to have _guaranteed_ supervision of the child, and link in order to
facilitate cascading EXITs. If the child unlinks from the supervisor,
it might mess up the cascading EXIT, but the supervisor must always be
able to detect a crashed child.


>> - The supervisor is able to execute in the started process before
>>   handing over control to the behaviour. This way, the supervisor
>>   can e.g. log information about _why_ the process is started
>>   (initial start?, restart?, escalated restart?) -- something that
>>   is not possible today.
>
>On the other hand, today the call-back process is able to execute in
>the supervisor before the process is started.  This feature can be
>used, and is used, in many interesting ways... ;-)

Yes, and I've been thinking that it would perhaps be better if the
supervisor was simply given a spec, and we do away with the callback 
completely. However, I realise that your smiley refers to my
sysSupervisor callback, which is most likely the most ambitious
supervisor callback yet -- even inventing atoms at runtime. (:
On second thought, we may want to keep the callback module.


>> A still open issue is whether behaviours which do _not_ want a 
>> process should also be allowed? Actually, we have one already:
>> application.
>
>And gen_event.  They should definitely be allowed!

Oh yes, I forgot about those. (:


/Uffe
-- 
Ulf Wiger                                    tfn: +46  8 719 81 95
Senior System Architect                      mob: +46 70 519 81 95
Strategic Product & System Management    ATM Multiservice Networks
Data Backbone & Optical Services Division      Ericsson Telecom AB




More information about the erlang-questions mailing list