I am an erlang newbie and I am trying to build my first messaging application. My question has 2 parts
When I open two separate erlang consoles on my terminal without specifying a -sname attribute how do both erlang consoles have the same process pids. Are they actually the same process, How?
Terminal #1
--------------
$> erl
Erlang R15B01 (erts-5.9.1) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> self().
0.31.0
Similarly for terminal 2
Erlang R15B01 (erts-5.9.1) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> self().
0.31.0
How can both be running on the same process. Are these erlang processes and not native processes?
If I am building a messaging application and I need some way to track the information of the message that is being sent by each user. The basic design I've tried to use is create a new chat client for each user. I spawn a process to keep track of the person who receives the message and thus store his nickname there.
Similarly i created another module that is used for keeping track of who sends the messages but in this case i used the self() Pid to keep track of senders. This takes place in the chat_client_sender
module.
-module(chat_client).
-export([start/0, stop/0, loop/1, login/3, logout/1, send_message/2]).
-define(SERVER, chat_client).
start() ->
message_router:start(),
chat_client_sender:start().
stop() ->
message_router:stop(),
chat_client_sender:stop().
login(Uid, Password, Nickname) ->
io:format("~p My Pid", [self()]),
Pid = spawn(chat_client, loop, [Nickname]),
case message_router:login(Uid, Password, Nickname, Pid) of
{ok, logged_in} ->
chat_client_sender:add_sender(self(), {Uid, Nickname}),
{ok, logged_in};
{error, invalid_uid_or_pwd} ->
{error, invalid}
end.
logout(Uid) ->
case message_router:logout(Uid) of
{ok, logged_out} ->
{ok, logged_out};
ignored ->
ignored;
_Someshit ->
io:format("Some Shit ~p", _Someshit)
end.
send_message(ToUid, MessageBody) ->
chat_client_sender:send_message(ToUid, MessageBody).
loop(Nickname) ->
receive
{print_msg, Messagebody, SenderNickname} ->
io:format("~p: ~p to ~p~n", [SenderNickname, Messagebody, Nickname]),
loop(Nickname);
stop ->
ok
end.
The chat_client_sender module
-module(chat_client_sender).
-export([start/0, stop/0, add_sender/2, loop/1, get_sender/1, send_message/2]).
-define(SERVER, chat_client_sender).
start() ->
erlang:register(?SERVER, spawn(chat_client_sender, loop, [dict:new()])).
stop() ->
?SERVER ! stop.
add_sender(SenderPid, {Uid, Nickname}) ->
io:format("Adding Sender ~p ~p ~p ~n", [SenderPid, Uid, Nickname]),
?SERVER ! {add_sender, SenderPid, {Uid, Nickname}}.
get_sender(SenderPid) ->
?SERVER ! {get_sender, SenderPid}.
send_message(ToUid, MessageBody) ->
?SERVER ! {send_msg, ToUid, MessageBody}.
loop(MemberPids) ->
receive
{add_sender, SenderPid, {Uid, Nickname}} ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
io:format("Pid exists ~n"),
loop(MemberPids);
error ->
loop(dict:store(SenderPid, {Uid, Nickname}, MemberPids))
end;
{send_msg, ToUid, MessageBody, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
{found, _Uid, Nickname} ->
message_router:send_message(ToUid, MessageBody, Nickname),
loop(MemberPids);
not_found ->
not_found,
loop(MemberPids)
end;
{remove_sender, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
{found, _Uid, _Nickname} ->
loop(dict:erase(SenderPid, MemberPids));
not_found ->
ignored,
loop(MemberPids)
end;
{get_sender, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
Any ->
io:format("GET SENDER ~p~n", [Any])
end,
loop(MemberPids);
stop ->
ok
end.
get_sender(SenderPid, MemberPids) ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
{found, {Uid, Nickname}};
error ->
not_found
end.
So my application begins to fail at add_sender
clause in my loop
method which stores the SenderPid arriving from the chat_client
.
Here is an example
chat_client:start().
true
9> chat_client_sender:add_sender(self(), {'sid@abc.com', 'sid'}).
Adding Sender 'sid@abc.com' sid
{add_sender,,{'sid@abc.com',sid}}
10> chat_client_sender:add_sender(self(), {'sid1@abc.com', 'sid1'}).
Adding Sender 'sid1@abc.com' sid1
{add_sender,,{'sid1@abc.com',sid1}}
11>
=ERROR REPORT==== 13-Oct-2012::19:12:42 ===
Error in process with exit value: {{case_clause,{ok,{'sid@abc.com',sid}}},[{chat_client_sender,loop,1,[{file,"chat_client_sender.erl"},{line,25}]}]}
As per my understanding it should simply continue with the tail recursion on the {ok, {Uid, Nickname}}
clause in the chat_client_sender
module.
...
receive
{add_sender, SenderPid, {Uid, Nickname}} ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
io:format("Pid exists ~n"),
loop(MemberPids);
error ->
loop(dict:store(SenderPid, {Uid, Nickname}, MemberPids))
end;
...
I would really appreciate some help understanding whats going on here. Also I would really appreciate it if you could review my code and tell me more about best practices and things that I could do better. My code is available at goo.gl/yY4kR
Thank you