anchor.diff:  -export([top/0]).
   
   -type state() :: { pdb:tableid(),
  -                   boolean(), %% monitoring is on
  -                   boolean(), %% output is on
  +                   false | all | pid, %% sampling: no, all or a single pid
  +                   false | all | pid, %% output: no, all, or a single pid
                      erlang_timestamp(), %% last output
                      non_neg_integer(), %% # of measures
                      non_neg_integer(), %% sort by
                      no_exclude | pid()
                    }.
   
  -
   -spec start_link(list()) -> {ok, pid()}.
   start_link(Group) ->
       gen_component:start_link(?MODULE, fun ?MODULE:on/2, [],
                                [{erlang_register, ?MODULE},
  -                             {pid_groups_join_as, Group, ?MODULE}]).
  +                              {pid_groups_join_as, Group, ?MODULE}]).
   
   -spec init([]) -> state().
   init([]) ->
  
positive.code:             "c" -> comm:send_local(Pid, {sort_by, cpuusage});
              "m" -> comm:send_local(Pid, {sort_by, memory});
              "t" -> comm:send_local(Pid, {toggle_exclude_self});
              "g" -> [garbage_collect(X) || X <- processes()];
              _ -> ok
      end,
      case Quit of
          quit -> ok;
          _ -> top_interactive(Pid)
      end.
  
  usage() ->
      io:format(
        "~n"
        " (q)uit, (e)val expr, (g)arb-coll."
        %% ", exclude (t)op itself" %% undocumented feature for top development
        "~n sort by: (c)pu usage (m)emory (p)ids (w)aiting messages~n").
  
  -spec on(comm:message(), state()) -> state().
  on({mon_on}, State) ->
      set_monitoring(State, true);
  
  on({output_on}, State) ->
      comm:send_local(self(), {output_data}),
      set_output(State, true);
  
  on({output_off}, State) ->
      comm:send_local(self(), {output_data}),
      set_output(State, false);
  
  on({sort_by, Type}, State) ->
      set_sort_by(State, Type);
  
  on({toggle_exclude_self}, State) ->
      toggle_exclude_self(State);
  
  on({start_mon}, State) when element(2, State) ->
      T = [ catch({X, erlang:process_info(X, [message_queue_len, status])})
            || X <- erlang:processes(), X =/= exclude_self(State) ],
  
  
negative.code:                 "~p", [Mem div 1024 div 1024 div 1024]))
              ++ "GB"
      end.
  
  readable_pid_name(Pid) ->
      Name = case pid_groups:group_and_name_of(Pid) of
                 failed ->
                     try element(2, process_info(Pid, registered_name))
                     catch _Level:_Reason ->
                             try_process_info(Pid, initial_call, dead_pid)
                     end;
                 N -> element(2, N)
             end,
      case is_list(Name) of
          false -> io_lib:write(Name);
          true -> Name
      end.
  
  readable_grp_and_pid_name(Pid) ->
      case pid_groups:group_and_name_of(Pid) of
          failed ->
              try element(2, process_info(Pid, registered_name))
              catch _Level:_Reason ->
                      try_process_info(Pid, initial_call, dead_pid)
              end;
          N -> N
      end.
  
  try_process_info(Pid, Types) ->
      try erlang:process_info(Pid, Types)
      catch _:_ -> []
      end.
  
  try_process_info(Pid, Type, DefaultVal) ->
      try element(2, erlang:process_info(Pid, Type))
      catch _:_ -> DefaultVal
      end.
  
  process_info_get(undefined, _Type, DefaultVal) ->
      DefaultVal;
  process_info_get(PropList, Type, DefaultVal) ->
      case lists:keyfind(Type, 1, PropList) of
          false -> DefaultVal;
          X -> element(2, X)
      end.
  