Designing a Concurrent Application - An Event Module (part IV)
Abstracting the cancel msg
So instead of having the user knowing how the message cancel is structured we're going to abstract it. Reminder of the cancel message structure: {Server, Ref, cancel}
Here's a reminder how loop is implemented to recieve the cancel message.
% ... receive {Server, Ref, cancel} -> Server ! {Ref, ok} % ...
So here's the abstraction or an interface to the cancel message:
cancel(Pid) -> %% Monitor in case the process is already dead Ref = erlang:monitor(process, Pid), Pid ! {self(), Ref, cancel}, receive {Ref, ok} -> erlang:demonitor(Ref, [flush]), ok; {'DOWN', Ref, process, Pid, _Reason} -> ok end.
It looks normal except for these new functions:
erlang:monitor(process, Pid)
erlang:demonitor(Ref, [flush])
"Oh! A new trick! Here I'm using a monitor to see if the process is there or not. If the process is already dead, I avoid useless waiting time and return ok as specified in the protocol. If the process replies with the reference, then I know it will soon die: I remove the reference to avoid receiving them when I no longer care about them. Note that I also supply the flush option, which will purge the DOWN message if it was sent before we had the time to demonitor."--book
"Oh! A new trick! Here I'm using a monitor to see if the process is there or not."
%% Monitor in case the process is already dead Ref = erlang:monitor(process, Pid),
"If the process is already dead, I avoid useless waiting time and return ok as specified in the protocol."
{'DOWN', Ref, process, Pid, _Reason} -> ok
"If the process replies with the reference, then I know it will soon die: I remove the reference to avoid receiving them when I no longer care about them. Note that I also supply the flush option, which will purge the DOWN message if it was sent before we had the time to demonitor."
{'DOWN', Ref, process, Pid, _Reason} -> ok
17> c(event). {ok,event} 18> f(). ok 19> event:start("Event", 0). <0.103.0> 20> flush(). Shell got {done,"Event"} ok 21> Pid = event:start("Event", 500). <0.106.0> 22> event:cancel(Pid). ok