To paraphrase a conversation I was having earlier.
A link is for bidirectional monitor
Now I understand the technical differences between the two. I.e. the need to make a process trap exits and different shaped messages.
My question is are the two things basically interchangeable or are there clearly distinct use-cases for one over the other? If so how do you identify what you use-case is and what’s the right solution to use.
Very distinct use-cases.
Like current GenEvent should have used monitors, currently you have to do a lot of bookkeeping with it (it pre-dates monitors).
But the differences:
Links: Auto transfer deaths both ways.
:normal will not kill anything else, anything else will unless trapped. You have to be sure to link at creation or the remote process ‘might’ already be dead by the time you are linked.
Monitors: Only send messages about all death results, nothing else. You can even monitor a process much ‘later’ and you will still get a message (saying it is not running), thus making it further great for monitoring. In addition it is trivial to ‘stop’ monitoring too.
Arguably, the most frequent case for links is OTP hierarchy, where the parent process is linked to the child. Another example is
Registry where the process being registered is linked to the registry process.
In both cases we need two-way termination propagation. A child should know that its parent has stopped, so it can stop itself. The same holds for a registered process, which should be made aware if a registry is taken down.
The default behaviour when exits are not trapped further ensures automatic termination of linked processes.
While in theory you could do this with monitors, it would be clumsier. For example, in the registry case, a registered process should monitor the registry, and then inform the registry (via a message) to monitor the registered process. Moreover, a registered process now needs to explicitly handle the
With links, you have an atomic one-liner which ensures out of the box that a registry knows about a registree termination, and also that the registree is taken down if the registry terminates. Of course, if a registree traps exits, it needs to handle the exit message explicitly, but even then a link solution is IMO much simpler than using two monitors.
So to summarize, I’d say that you want to use links when you want to atomically create a bidirectional propagation of process termination (A knows about B’s termination and vice versa).
The way I rationalize it is that links are used to group (“link”) multiple processes that are collaborating towards on one common high level goal - that needs to be abandoned wholesale once any one of them determines that the goal is no longer attainable. The process that happens to arrive at this conclusion first then exits abnormally in order to terminate all of it’s collaborators.
Trapping exits shouldn’t necessarily be seen as a “survival strategy” but as a means for a process to have a chance to “settle its affairs” (i.e. release resources) while terminating - and it won’t even get a chance to do that if the exit reason is “:kill”.
Monitoring is just that - keeping tabs on a process you usually have outsourced some work to - and if it unexpectedly dies (or takes too long - as determined in combination with
Process.send_after/4), you can take whatever action is appropriate given your particular situation - all without having to get into trapping exits. Just because your outsourced work dies doesn’t mean you should go down with it. The only disadvantage is that if you go down, your “outsourced work” will continue on - which often isn’t desired.
There’s also another important aspect - you can link processes only once, while a monitor can be set up multiple times (and you’ll receive multiple messages).
This makes monitors much more useful for libraries that need to temporarily react to the lifecycle of other processes, especially if such calls could be nested. Each function/component will receive their own
DOWN message, while link, even if trapping exits, will only ever deliver the message once.
For me, this differentiates the use cases: links for fundamental dependencies between processes and monitors for more temporary relations.
That is a really helpful selection of points.
A post was split to a new topic: Designing Supervision Trees