
[;1m  monitor(Type, Item)[0m

  Sends a monitor request of type [;;4mType[0m to the entity identified by [;;4m[0m
  [;;4mItem[0m.

  If the monitored entity does not exist or it changes monitored
  state, the caller of [;;4mmonitor/2[0m is notified by a message on the
  following format:

    {Tag, MonitorRef, Type, Object, Info}

  [;;4mNote[0m

    The monitor request is an asynchronous signal. That is, it
    takes time before the signal reaches its destination.

  [;;4mType[0m can be one of the following atoms: [;;4mprocess[0m, [;;4mport[0m or [;;4m[0m
  [;;4mtime_offset[0m.

  A [;;4mprocess[0m or [;;4mport[0m monitor is triggered only once, after that
  it is removed from both monitoring process and the monitored
  entity. Monitors are fired when the monitored process or port
  terminates, does not exist at the moment of creation, or if the
  connection to it is lost. If the connection to it is lost, we do
  not know if it still exists. The monitoring is also turned off
  when [;;4mdemonitor/1[0m is called.

  A [;;4mprocess[0m or [;;4mport[0m monitor by name resolves the [;;4mRegisteredName[0m
  to [;;4mpid/0[0m or [;;4mport/0[0m only once at the moment of monitor
  instantiation, later changes to the name registration will not
  affect the existing monitor.

  When a [;;4mprocess[0m or [;;4mport[0m monitor is triggered, a [;;4m'DOWN'[0m
  message is sent that has the following pattern:

    {'DOWN', MonitorRef, Type, Object, Info}

  In the monitor message [;;4mMonitorRef[0m and [;;4mType[0m are the same as
  described earlier, and:

   • [;;4mObject[0m - The monitored entity, which triggered the event.
     When monitoring a process or a local port, [;;4mObject[0m will be
     equal to the [;;4mpid/0[0m or [;;4mport/0[0m that was being monitored.
     When monitoring process or port by name, [;;4mObject[0m will have
     format [;;4m{RegisteredName, Node}[0m where [;;4mRegisteredName[0m is
     the name which has been used with [;;4mmonitor/2[0m call and [;;4mNode[0m
     is local or remote node name (for ports monitored by name, [;;4m[0m
     [;;4mNode[0m is always local node name).

   • [;;4mInfo[0m - Either the exit reason of the process, [;;4mnoproc[0m
     (process or port did not exist at the time of monitor
     creation), or [;;4mnoconnection[0m (no connection to the node
     where the monitored process resides).

   • Monitoring a [;;4mprocess[0m - Creates monitor between the current
     process and another process identified by [;;4mItem[0m, which can
     be a [;;4mpid/0[0m (local or remote), an atom [;;4mRegisteredName[0m or
     a tuple [;;4m{RegisteredName, Node}[0m for a registered process,
     located elsewhere.

  [;;4mChange[0m

       Before ERTS 10.0 (OTP 21.0), monitoring a process could
       fail with [;;4mbadarg[0m if the monitored process resided on a
       primitive node (such as erl_interface or jinterface),
       where remote process monitoring is not implemented. Now,
       such a call to [;;4mmonitor[0m will instead succeed and a
       monitor is created. But the monitor will only supervise
       the connection. That is, a [;;4m{'DOWN', _, process, _,[0m
       [;;4mnoconnection}[0m is the only message that may be received,
       as the primitive node have no way of reporting the
       status of the monitored process.

   • Monitoring a [;;4mport[0m - Creates monitor between the current
     process and a port identified by [;;4mItem[0m, which can be a [;;4m[0m
     [;;4mport/0[0m (only local), an atom [;;4mRegisteredName[0m or a tuple [;;4m[0m
     [;;4m{RegisteredName, Node}[0m for a registered port, located on
     this node. Note, that attempt to monitor a remote port will
     result in [;;4mbadarg[0m.

     Available since OTP 19.0.

   • Monitoring a [;;4mtime_offset[0m - Monitors changes in [;;4m[0m
     [;;4mtime_offset/0[0m between Erlang monotonic time and Erlang
     system time. One valid [;;4mItem[0m exists in combination with the [;;4m[0m
     [;;4mtime_offset Type[0m, namely the atom [;;4mclock_service[0m. Notice
     that the atom [;;4mclock_service[0m is not the registered name
     of a process. In this case it serves as an identifier of the
     runtime system internal clock service at current runtime
     system instance.

     The monitor is triggered when the time offset is changed.
     This either if the time offset value is changed, or if the
     offset is changed from preliminary to final during
     finalization of the time offset when the single time warp
     mode is used. When a change from preliminary to final time
     offset is made, the monitor is triggered once regardless of
     whether the time offset value was changed or not.

     If the runtime system is in multi time warp mode, the time
     offset is changed when the runtime system detects that the
     OS system time has changed. The runtime system does,
     however, not detect this immediately when it occurs. A task
     checking the time offset is scheduled to execute at least
     once a minute, so under normal operation this is to be
     detected within a minute, but during heavy load it can take
     longer time.

     The monitor is not automatically removed after it has been
     triggered. That is, repeated changes of the time offset
     trigger the monitor repeatedly.

     When the monitor is triggered a [;;4m'CHANGE'[0m message is sent
     to the monitoring process. A [;;4m'CHANGE'[0m message has the
     following pattern:

       {'CHANGE', MonitorRef, Type, Item, NewTimeOffset}

     where [;;4mMonitorRef[0m, [;;4mType[0m, and [;;4mItem[0m are the same as
     described above, and [;;4mNewTimeOffset[0m is the new time offset.

     When the [;;4m'CHANGE'[0m message has been received you are
     guaranteed not to retrieve the old time offset when calling [;;4m[0m
     [;;4merlang:time_offset/0[0m. Notice that you can observe the
     change of the time offset when calling [;;4merlang:time_offset/0[0m
     before you get the [;;4m'CHANGE'[0m message.

     Available since OTP 18.0.

  Making several calls to [;;4mmonitor/2[0m for the same [;;4mItem[0m and/or [;;4m[0m
  [;;4mType[0m is not an error; it results in as many independent
  monitoring instances.

  The monitor functionality is expected to be extended. That is,
  other [;;4mType[0ms and [;;4mItem[0ms are expected to be supported in a future
  release.

  [;;4mNote[0m

    If or when [;;4mmonitor/2[0m is extended, other possible values for [;;4m[0m
    [;;4mTag[0m, [;;4mObject[0m, and [;;4mInfo[0m in the monitor message will be
    introduced.

  [;;4mNote[0m

    For some important information about distributed signals, see
    the Blocking Signaling Over Distribution section in the 
    Processes chapter of the Erlang Reference Manual.

[;1m  monitor(Type, Item, Opts)[0m

[;;4mSince[0m:
  OTP 24.0

  Provides an option list for modification of monitoring
  functionality provided by [;;4mmonitor/2[0m. The [;;4mType[0m and [;;4mItem[0m
  arguments have the same meaning as when passed to [;;4mmonitor/2[0m.

  Currently available options:

   • [;;4m{alias, UnaliasOpt}[0m - The returned monitor reference will
     also become an alias for the calling process. That is, the
     returned reference can be used for sending messages to the
     calling process. See also [;;4malias/0[0m. The [;;4mUnaliasOpt[0m
     determines how the alias should be deactivated.

      ￮ [;;4mexplicit_unalias[0m - Only an explicit call to [;;4m[0m
        [;;4munalias/1[0m will deactivate the alias.

      ￮ [;;4mdemonitor[0m - The alias will be automatically
        deactivated when the monitor is removed. This either
        via an explicit call to [;;4mdemonitor/1[0m or when it is
        automatically removed at the same time as a [;;4m'DOWN'[0m
        message is delivered due to the monitor. The alias can
        also still be deactivated via a call to [;;4munalias/1[0m.

      ￮ [;;4mreply_demonitor[0m - The alias will be automatically
        deactivated when the monitor is removed (see [;;4m[0m
        [;;4mdemonitor[0m option above) or a reply message sent via
        the alias is received. When a reply message is
        received via the alias the monitor will also be
        automatically removed. This is useful in client/server
        scenarios when a client monitors the server and will
        get the reply via the alias. Once the response is
        received both the alias and the monitor will be
        automatically removed regardless of whether the
        response is a reply or a [;;4m'DOWN'[0m message. The alias
        can also still be deactivated via a call to [;;4munalias/1[0m.
        Note that if the alias is removed using the [;;4munalias/1[0m
        BIF, the monitor will still be left active.

     Example:

       server() ->
           receive
               {request, AliasReqId, Request} ->
                   Result = perform_request(Request),
                   AliasReqId ! {reply, AliasReqId, Result}
           end,
           server().
       
       client(ServerPid, Request) ->
           AliasMonReqId = monitor(process, ServerPid, [{alias, reply_demonitor}]),
           ServerPid ! {request, AliasMonReqId, Request},
           %% Alias as well as monitor will be automatically deactivated if we
           %% receive a reply or a 'DOWN' message since we used 'reply_demonitor'
           %% as unalias option...
           receive
               {reply, AliasMonReqId, Result} ->
                   Result;
               {'DOWN', AliasMonReqId, process, ServerPid, ExitReason} ->
                   error(ExitReason)
           end.

     Note that both the server and the client in this example
     must be executing on at least OTP 24 systems in order for
     this to work.

     For more information on process aliases see the Process
     Aliases section of the Erlang Reference Manual.

   • [;;4m{tag, UserDefinedTag}[0m - Replace the default [;;4mTag[0m with [;;4m[0m
     [;;4mUserDefinedTag[0m in the monitor message delivered when the
     monitor is triggered. For example, when monitoring a
     process, the [;;4m'DOWN'[0m tag in the down message will be
     replaced by [;;4mUserDefinedTag[0m.

     An example of how the [;;4m{tag, UserDefinedTag}[0m option can be
     used in order to enable the new selective receive
     optimization, introduced in OTP 24, when making multiple
     requests to different servers:

       server() ->
           receive
               {request, From, ReqId, Request} ->
                   Result = perform_request(Request),
                   From ! {reply, self(), ReqId, Result}
           end,
           server().
       
       client(ServerPids, Request) when is_list(ServerPids) ->
           ReqId = make_ref(),
           lists:foreach(fun (ServerPid) ->
                                 _ = monitor(process, ServerPid,
                                             [{tag, {'DOWN', ReqId}}]),
                                 ServerPid ! {request, self(), ReqId, Request}
                         end,
                         ServerPids),
           receive_replies(ReqId, length(ServerPids), []).
       
       receive_replies(_ReqId, 0, Acc) ->
           Acc;
       receive_replies(ReqId, N, Acc) ->
           %% The compiler will detect that we match on the 'ReqId'
           %% reference in all clauses, and will enable the selective
           %% receive optimization which makes the receive able to
           %% skip past all messages present in the message queue at
           %% the time when the 'ReqId' reference was created...
           Res = receive
                     {reply, ServerPid, ReqId, Result} ->
                         %% Here we typically would have deactivated the
                         %% monitor by a call to demonitor(Mon, [flush]) but
                         %% we ignore this in this example for simplicity...
                         {ok, ServerPid, Result};
                     {{'DOWN', ReqId}, _Mon, process, ServerPid, ExitReason} ->
                         {error, ServerPid, ExitReason}
                 end,
           receive_replies(ReqId, N-1, [Res | Acc]).

     In order for this example to work as intended, the client
     must be executing on at least an OTP 24 system, but the
     servers may execute on older systems.
