Solution 11-4
Here is a suggested solution for Étude 11-4.
chatroom.erl
-
module
(
chatroom
).
-
behaviour
(
gen_server
).
-
export
([
start_link
/
0
]).
% convenience call for startup
-
export
([
init
/
1
,
handle_call
/
3
,
handle_cast
/
2
,
handle_info
/
2
,
terminate
/
2
,
code_change
/
3
]).
% gen_server callbacks
-
define
(
SERVER
,
?
MODULE
).
% macro that defines this module as the server
% The server state consists of a list of tuples for each person in chat.
% Each tuple has the format {{UserName, UserServer}, PID of person}
%%% convenience method for startup
start_link
()
->
gen_server
:
start_link
({
local
,
?
SERVER
},
?
MODULE
,
[],
[]).
%%% gen_server callbacks
init
([])
->
{
ok
,
[]}.
%% Check to see if a user name/server pair is unique;
%% if so, add it to the server's state
handle_call
({
login
,
UserName
,
ServerRef
},
From
,
State
)
->
{
FromPid
,
_
FromTag
}
=
From
,
case
lists
:
keymember
({
UserName
,
ServerRef
},
1
,
State
)
of
true
->
NewState
=
State
,
Reply
=
{
error
,
"User "
++
UserName
++
" already in use."
};
false
->
NewState
=
[{{
UserName
,
ServerRef
},
FromPid
}
|
State
],
Reply
=
{
ok
,
"Logged in."
}
end
,
{
reply
,
Reply
,
NewState
};
%% Log out the person sending the message, but only
%% if they're logged in already.
handle_call
({
logout
},
From
,
State
)
->
{
FromPid
,
_
FromTag
}
=
From
,
case
lists
:
keymember
(
FromPid
,
2
,
State
)
of
true
->
NewState
=
lists
:
keydelete
(
FromPid
,
2
,
State
),
Reply
=
{
ok
,
logged_out
};
false
->
NewState
=
State
,
Reply
=
{
error
,
not_logged_in
}
end
,
{
reply
,
Reply
,
NewState
};
%% When receiving a message from a person, ...
Get Études for Erlang now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.