
  [;1m-spec monitor(process, monitor_process_identifier(), [monitor_option()]) ->[0m
  [;1m                 MonitorRef[0m
  [;1m                 when MonitorRef :: reference();[0m
  [;1m             (port, monitor_port_identifier(), [monitor_option()]) ->[0m
  [;1m                 MonitorRef[0m
  [;1m                 when MonitorRef :: reference();[0m
  [;1m             (time_offset, clock_service, [monitor_option()]) ->[0m
  [;1m                 MonitorRef[0m
  [;1m                 when MonitorRef :: reference().[0m

[;;4mSince[0m:
  OTP 24.0

  Types:
    -type monitor_port_identifier() :: port() | registered_name().
    -type monitor_process_identifier() ::
          pid() | registered_process_identifier().
    -type registered_name() :: atom().
    -type registered_process_identifier() ::
          registered_name() | {registered_name(), node()}.

  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[;;4m{alias, UnaliasOpt}[0m[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 [;;4m[0m
    [;;4malias/0[0m. The [;;4mUnaliasOpt[0m determines how the alias should be
    deactivated.

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

    [;;4m[;;4mdemonitor[0m[0m:
      The alias will be automatically deactivated when the
      monitor is removed. This either via an explicit call to [;;4m[0m
      [;;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.

    [;;4m[;;4mreply_demonitor[0m[0m:
      The alias will be automatically deactivated when the
      monitor is removed (see [;;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[0m
      [;;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[;;4m{tag, UserDefinedTag}[0m[0m:
    Replace the default [;;4mTag[0m with [;;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.
