anchor.diff:  -type erl_local_pid_plain() :: pid() | reg_name().
   -type erl_local_pid_with_cookie() :: {erl_local_pid_plain(), c, cookie()}.
   -type erl_local_pid() :: erl_local_pid_plain() | erl_local_pid_with_cookie().
  --type erl_pid_plain() :: erl_local_pid_plain() | {reg_name(), node()}. % port() | 
  -
  +-type erl_pid_plain() :: erl_local_pid_plain() | {reg_name(), node()}. % port()
   
   -ifdef(TCP_LAYER).
   -type mypid_plain() :: {inet:ip_address(), integer(), erl_pid_plain()}.
  
positive.code: -ifdef(BUILTIN).
  -type mypid_plain() :: erl_pid_plain().
  -endif.
  
  
  %% -type erl_pid_with_cookie() :: {erl_pid_plain(), c, cookie()}.
  %% -type erl_pid() :: erl_pid_plain() | erl_pid_with_cookie().
  
negative.code: -type message() :: message_plain() | message_with_cookie().
  -type group_message() :: {send_to_group_member, atom(), message()}.
  
  %% @doc Sends a message to a process given by its pid.
  -spec send(mypid(), message() | group_message()) -> ok.
  -ifdef(TCP_LAYER).
  send(Pid, Message) ->
      {RealPid, RealMessage} = unpack_cookie(Pid, Message),
      comm_layer:send(RealPid, RealMessage).
  -endif.
  -ifdef(BUILTIN). %% @hidden
  send(Pid, Message) ->
      {RealPid, RealMessage} = unpack_cookie(Pid, Message),
      send_local(RealPid, RealMessage).
  -endif.
  
  %% @doc Sends a message to a local process given by its local pid
  %%      (as returned by self()).
  -spec send_local(erl_local_pid(), message()) -> ok.
  send_local(Pid, Message) ->
      {RealPid, RealMessage} = unpack_cookie(Pid, Message),
      RealPid ! RealMessage,
      ok.
  
  %% @doc Sends a message to a local process given by its local pid
  %%      (as returned by self()) after the given delay in milliseconds.
  -spec send_local_after(non_neg_integer(), erl_local_pid(), message()) -> reference().
  send_local_after(Delay, Pid, Message) ->
      {RealPid, RealMessage} = unpack_cookie(Pid, Message),
      erlang:send_after(Delay, RealPid, RealMessage).
  
  %% @doc Sends a message to an arbitrary process of another node instructing it
  %%      to forward the message to a process in its group with the given name.
  -spec send_to_group_member(mypid(), atom(), message()) -> ok.
  send_to_group_member(DestNode, Processname, Mesg) ->
      send(DestNode, {send_to_group_member, Processname, Mesg}).
  
  -spec make_global(erl_pid_plain()) -> mypid().
  -ifdef(TCP_LAYER).
  %% @doc TCP_LAYER: Converts a local erlang pid to a global pid of type mypid()
  %%      for use in send/2.
  make_global(Pid) -> get(Pid, comm:this()).
  -endif.
  -ifdef(BUILTIN).
  %% @doc BUILTIN: Returns the given pid (with BUILTIN communication, global pids
  %%      are the same as local pids) for use in send/2.
  make_global(Pid) -> Pid.
  -endif.
  
  -spec make_local(mypid()) -> erl_pid_plain().
  -ifdef(TCP_LAYER).
  %% @doc TCP_LAYER: Converts a global mypid() of the current node to a local
  %%      erlang pid.
  make_local(Pid) -> comm_layer:make_local(Pid).
  -endif.
  -ifdef(BUILTIN).
  %% @doc BUILTIN: Returns the given pid (with BUILTIN communication, global pids
  %%      are the same as local pids).
  make_local(Pid) -> Pid.
  -endif.
  
  %% @doc Returns the pid of the current process.
  -spec this() -> mypid().
  -ifdef(TCP_LAYER).
  this() -> comm_layer:this().
  -endif.
  -ifdef(BUILTIN). %% @hidden
  this() -> self().
  -endif.
  
  %% @doc Creates the PID a process with name Name would have on node _Node.
  -spec get(erl_pid_plain(), mypid()) -> mypid().
  -ifdef(TCP_LAYER).
  get(Name, {Pid, c, Cookie} = _Node) -> {get(Name, Pid), c, Cookie};
  get(Name, {IP, Port, _Pid} = _Node) -> {IP, Port, Name}.
  -endif.
  -ifdef(BUILTIN). %% @hidden
  get(Name, {Pid, c, Cookie} = _Node) -> {get(Name, Pid), c, Cookie};
  get(Name, {_Pid, Host} = _Node) when is_atom(Name) -> {Name, Host};
  get(Name, Pid = _Node) when is_atom(Name) -> {Name, node(Pid)};
  get(Name, Pid = _Node) ->
      A = node(Name),
      A = node(Pid), % we assume that you only call get with local pids
      Name.
  -endif.
  
  %% @doc Encapsulates the current process' pid (as returned by this/0)
  %%      and the given cookie for seamless use of cookies with send/2.
  -spec this_with_cookie(any()) -> mypid_with_cookie().
  this_with_cookie(Cookie) -> {this(), c, Cookie}.
  
  %% @doc Encapsulates the current process' pid (as returned by self/0) and the
  %%      given cookie for seamless use of cookies with send_local/2 and
  %%      send_local_after/3.
  -spec self_with_cookie(any()) -> erl_local_pid_with_cookie().
  self_with_cookie(Cookie) -> {self(), c, Cookie}.
  
  -spec is_valid(mypid() | any()) -> boolean().
  %% @doc Checks if the given pid is valid.
  -ifdef(TCP_LAYER).
  is_valid({Pid, c, _Cookie}) -> is_valid(Pid);
  is_valid(Pid) -> comm_layer:is_valid(Pid).
  -endif.
  -ifdef(BUILTIN). %% @hidden
  is_valid({Pid, c, _Cookie}) -> is_valid(Pid);
  is_valid(Pid) when is_pid(Pid) orelse is_atom(Pid) orelse is_port(Pid) -> true;
  is_valid({RegName, _Node}) when is_atom(RegName)                       -> true;
  is_valid(_) -> false.
  -endif.
  
  -spec is_local(mypid()) -> boolean().
  -ifdef(TCP_LAYER).
  %% @doc TCP_LAYER: Checks whether a global mypid() can be converted to a local
  %%      pid of the current node.
  is_local(Pid) -> comm_layer:is_local(Pid).
  -endif.
  -ifdef(BUILTIN).
  %% @doc BUILTIN: Checks whether a pid is located at the same node than the
  %%      current process.
  is_local(Pid) -> erlang:node(Pid) =:= node().
  -endif.
  
  %% @doc Gets the tag of a message (the first element of its tuple - should be an
  %%      atom).
  -spec get_msg_tag(message() | group_message()) -> atom().
  get_msg_tag({Message, _Cookie})
    when is_tuple(Message) andalso is_atom(erlang:element(1, Message)) ->
      get_msg_tag(Message);
  get_msg_tag({send_to_group_member, _ProcessName, Message})
    when is_tuple(Message) andalso is_atom(erlang:element(1, Message)) ->
      get_msg_tag(Message);
  get_msg_tag(Message)
    when is_tuple(Message) andalso is_atom(erlang:element(1, Message)) ->
      erlang:element(1, Message).
  
  unpack_cookie({Pid, c, Cookie}, Message) -> {Pid, {Message, Cookie}};
  unpack_cookie(Pid, Message) -> {Pid, Message}.
  