Related
There's variable in my module, and there's receive method to renew variable value. And multiple process are calling this method simultaneously. I need lock this variable when one process is modifying it. Sample as below
mytest.erl
%%%-------------------------------------------------------------------
-module(mytest).
%% API
-export([start_link/0,display/1,callDisplay/2]).
start_link()->
Pid=spawn(mytest,display,["Hello"]),
Pid.
display(Val) ->
io:format("It started: ~p",[Val]),
NextVal=
receive
{call,Msg}->
NewVal=Val++" "++Msg++" ",
NewVal;
stop->
true
end,
display(NextVal).
callDisplay(Pid,Val)->
Pid!{call,Val}.
Start it
Pid=mytest:start_link().
Two process are calling it in the same time
P1=spawn(mytest,callDisplay,[Pid,"Walter"]),
P2=spawn(mytest,callDisplay,[Pid,"Dave"]).
I hope it can add "Walter", "Dave" one by one like "Hello Walter Dave", however, when there're too many of them running together, some Names(Walter, Dave, etc) will be override.
Because when P1, P2 started the same time, Val both are "Hello". P1 add "Walter" to become "Hello Walter", P2 add "Dave" to become "Hello Dave". P1 saved it firstly to NextVal as "Hello Walter", then P2 saved it to NextVal as "Hello Dave", so result will be "Hello Dave". "Hello Walter" is replaced by "Hello Dave", and "Walter" lost forever.
Is there any way I can lock "Val", so when we add "Walter", "Dave" will waiting till Value setting is done?
Even though it's an old question but it's worth explaining.
From what you said and if I'm correct,
you expect to see
"Hello Walter", and "Hello Dave". However, you're seeing successive names been appended to the former as, "Hello Walter Dave.."
This behavior is normal and to see that let look briefly at Erlang memory model. Erlang process memory is divided into three main parts:
Process Control Block(PCB):
This hold the process pid, registered name,table,states and pointers to messages in the it's queue.
Stack:
This hold function parameters, local variables and function return address.
Private Heap: This hold incoming message compound data like tuple, list and binary(not larger than 64 bytes).
All data in these memory belong to and are private to the owning process.
Stage1:
When Pid=spawn(mytest,display,["Hello"]) is called, the server process is created, then the display function with "Hello" passed as argument is called. Since display/1 is executed in the serve process, the "Hello" argument lives in the server's process stack. Execution of display/1 continues until it reaches the receive clause then block and await message matching your format.
Stage 2:
Now P1 starts, it executes ServerPid ! {call, "Walter"}, then P2 executes ServerPid ! {call, "Dave"}. In both cases, erlang makes a copy of the message and send it to the server's process mailbox (Private Heap). This copied message in the mailbox belongs to the server process not the client's.
Now, when {call, "Walter"} is matched, Msg get bound to "Walter".
From stage1, we know Val is bounded to "Hello", Newval then get bounded to "Val ++ " " ++ Msg" = "Hello Walter".
At this point, P2's message, {call, "Dave"}, is still in the server's mailbox awaiting the next receive clause which will happen in the next recursive call to display/1. NextVal get bound to NewVal and the recursive call to dispaly/1 with "Hello Walter" passed as argument is made. This gives the first print "Hello Walter " which now also lives in the server's process stack.
Now when the receive clause is reach again, P2's message {call, "Dave"} is matched.
Now NewVal and NextVal get bound to "Hello Walter" ++ " " ++ "Dave" = "Hello Walter Dave". This get passed as argument to display/1 as the new Val to print Hello Walter Dave. In a nutshell, this variable is updated on every server loop. It serves the same purpose as the State term in gen_server behavior. In your case, successive client calls just appends the message to this serve state variable. Now to your question,
Is there any way I can lock Val, so when we add "Walter", "Dave" will waiting till Value setting is done?
No. Not by locking. Erlang does not work this way.
There are no process locking constructs as it does not need one.
Data(Variables) are always immutable and private(except large binaries which stays in the Shared Heap) to the process that created it.
Also, it's not the actual message you used in the Pid ! Msg construct that is process by the receiving process. It's it copy. The Val parameter in yourdisplay/1 function is private and belongs to the server process because it lives in it stack memory as every call to display/1 is made by the server process itself. So there is no way any other process can lock not even see that variable.
Yes. By sequential message processing
This is exactly what the server process is doing. Polling one message a time from it queue. When {call, "Walter"} was taken, {call, "Dave"} was waiting in the queue. The reason why you see unexpected greeting is because the you change the server state, the display/1 parameter for the next display/1 call which process {call, "Dave"}
So I got a hook in my code that says if an offline message is received, it will start up this function.
offline_msg_received(From, To, Packet) ->
The Packet has code looking like this:
{message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}
What I wanted out of this is the part containing my message. Which is:
[{text,<<>>,<<"Hello">>}]
I could get this part out with a pattern matching against the whole package variable. However, when I tried a pattern matching with my message, it says bad argument. I know that if I specify a variable with just
{text,<<>>,<<"Hello">>}
then I can pattern match against that. From my understanding, seeing [ ] around something means it is a list, or a string.
I can show some of the code here.
{P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11} = Packet, %% P8 is the message I want.
?INFO_MSG("----------------------P8: ~p~n", P8), %% This shows {text,<<>>,<<"Hello">>}
{A, B, C} = P8, %% This gives me a badmatch error.
Now, if I were to instead do this manually in the code shell:
{text,<<>>,<<"Hello">>} = P8,
{A, B, C} = P8,
Then the code works, and puts <<"Hello">> in the C variable.
My guess is that the [ ] around it in the "Package" variable has something to do with my badmatch error, but for some reason those symbols don't appear when I print out P8. Does anyone have a good suggestion why it doesn't work? I am guessing it has something to do with the hidden [ ], since otherwise it looks identical to my shell code test.
Thanks. This is my first time asking questions here, so I hope I didn't do anything wrong.
The reason you're not seeing the square brackets around the value in your INFO_MSG call is that INFO_MSG expects a list of values, not just a single value. In the code above it happens to work out, since the format string only contains a single directive, and the value is a list of one element, so that's why the brackets are silently stripped out.
The INFO_MSG macro works the same as io:format, so you could try this out in the shell:
%% two arguments
io:format("~p ~p\n", [foo, bar]).
%% one argument - we still need square brackets
io:format("~p\n", [foo]).
You're doing this the hard way :) message and text are records defined in xmpp_codec.hrl. If you don't have the record definitions loaded in the shell, records look like a tuple with lots of elements, but if you load the record definitions, your message looks like this instead:
1> rr("include/xmpp_codec.hrl").
[address,addresses,adhoc_actions,adhoc_command,adhoc_note,
bind,block,block_list,bob_data,bookmark_conference,
bookmark_storage,bookmark_url,bytestreams,caps,
carbons_disable,carbons_enable,carbons_private,
carbons_received,carbons_sent,chatstate,client_id,compress,
compress_failure,compressed,compression,csi,db_feature,
db_result,db_verify|...]
2> {message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}.
#message{id = <<"purple2d957668">>,type = chat,lang = <<>>,
from = undefined,
to = {jid,<<"admin">>,<<"localhost">>,<<"5280">>,
<<"admin">>,<<"localhost">>,<<"5280">>},
subject = [],
body = [#text{lang = <<>>,data = <<"Hello">>}],
thread = undefined,
sub_els = [{xmlel,<<"active">>,
[{<<"xmlns">>,
<<"http://jabber.org/protocol/chatstates">>}],
[]}],
meta = #{}}
The data you are looking for is in the body field.
Let's assign this record to the variable M and extract the body field:
4> Body = M#message.body.
[#text{lang = <<>>,data = <<"Hello">>}]
So that's a list containing one text record. Let's extract the data field from that:
6> [#text{data = Data}] = Body.
[#text{lang = <<>>,data = <<"Hello">>}]
7> Data.
<<"Hello">>
That's how it works in the shell - load the record definitions with the rr function. When writing a module that uses record definitions, you'd need to include the hrl file:
-include_lib("xmpp/include/xmpp_codec.hrl").
The -include_lib directory will look for the xmpp application on the load path, and search for the file xmpp_codec.hrl inside its include directory. You may need to specify the code path to the compiler, something like erlc -pa path/to/xmpp/ebin my_module.erl - note that the ebin directory inside the application should be on the code path.
I'm trying to understand request order in erlang, but I can't seem to grasp it very well. Here's the example code:
test() ->
Server = start(),
spawn(fun() -> write(Server, 2),
io:format(”Child 1 read ~p~n”, [read(Server)]) end),
write(Server, 3),
write2(Server, 5),
spawn(fun() -> write2(Server, 1),
io:format(”Child 2 read ~p~n”, [read(Server)]) end),
io:format(”Parent read ~p~n”, [read(Server)]).
And here's the server:
start() ->
spawn(fun() -> init() end).
init() -> loop(0).
loop(N) ->
receive
{read, Pid} ->
Pid ! {value, self(), N},
loop(N);
{write, Pid, M} ->
Pid ! {write_reply, self()},
loop(M);
{write2, _Pid, M} -> loop(M)
end.
read(Serv) ->
Serv ! {read, self()},
receive {value, Serv, N} -> N end.
write(Serv, N) ->
Serv ! {write, self(), N},
receive {write_reply, Serv} -> ok end.
write2(Serv, N) ->
Serv ! {write2, self(), N},
ok.
I understand that different values could be printed by the three different processes created in test/0, but I'm trying to figure out the lowest and highest values that could be printed by those Parent, Child1 and Child2 processes. The answer states:
Parent: lowest 1, highest 5
Child1: lowest 1, highest 5
Child2: lowest 1, highest 2
Can somebody explain this?
Keep in mind that Erlang guarantees message order only from one process to another. If process A sequentially sends message 1 and then message 2 to process B, then B will receive them in that order. But Erlang guarantees no specific ordering of messages arriving at B if multiple concurrent processes are sending them. In this example, Parent, Child1, and Child2 all run concurrently and all send messages concurrently to Server.
The Parent process performs the following sequential steps:
Spawns the Server process. This eventually sets the initial value in the Server loop to 0.
Spawns Child1. This eventually writes the value 2 to Server, then reads from Server and prints the result.
Uses write/2 to send the value 3 to Server. The write case in the loop/1 function first replies to the caller and then installs the value 3 for its next iteration.
Uses write2/2 to send 5 to Server. The write2/2 function just sends a message to Server and does not await a reply. The write2 case in the loop/1 function just installs the value 5 for its next iteration.
Spawns Child2, which eventually calls write2/2 with the value 1, and then reads Server and prints the result.
Reads Server and prints the result.
For Parent, step 3 sends the value 3 to Server, so as far as Parent is concerned, Server now has the value 3. In step 4, Parent calls write2/2 to send 5 to the server, and that message must arrive at Server sometime after the message sent in step 3. In step 6, Parent performs a read, but all we know is that this message has to arrive at Server after the write message in step 4. This message ordering means the highest value Parent can see is 5.
The lowest value Parent can see is 1 because if Child2 gets its write message of 1 to Server after the Parent write message of 5 but before the final Parent read message, then Parent will see the 1.
For Child1, the highest value it can see is 5 because it runs concurrently with Parent and the two messages sent by Parent could arrive at Server before its write message of 2. The lowest Child1 can see is 1 because the Child2 write message of 1 can arrive before the Child1 read message.
For Child2, the lowest value it can see is its own write of 1. The highest value it can see is 2 from the write of Child1 because the Parent writes of 3 and 5 occur before Child2 is spawned, thus Child1 is the only process writing concurrently and so only it has a chance of interleaving its write message between the Child2 write and read messages.
I am trying to build a very simple barrier-synchronization server, where the server is initially fed a number of processes that will be communicating with it. When a process is done, it receives a message with that process' Pid, and it keeps a list of every process to do so. When the barrier reaches zero (all processes have sent messages), my server needs to send a message to each of these (I am using [Pid | ProcList] as my list of pids).
I have tried using a helper function to no avail, list comprehensions keep me in an infinite loop, and as such I am looking into how to use lists:foreach to take care of this.
I am fairly new to functional programming, but from what I understand, this foreach needs to take in the list as well as a lambda-calculus function to send a message to each node in the list. Due to the infix nature of "!", I have yet to find a way to do this without causing syntax errors.
How you've made infinite loop in list comprehension? I must say, that's quite challenging. Try this:
Message = % broadcast message goes here
ListOfPids = % list of recipients
[Pid ! Message || Pid <- ListOfPids].
If you want to use foreach, than it takes one argument function as first argument, so need to wrap send first, as it is two argument function.
Message = % broadcast message goes here
ListOfPids = % list of recipients
Fun = fun (Pid) -> Pid ! Message end,
lists:foreach(Fun, ListOfPids).
Can someone explain the structure of a Pid in Erlang?
Pids looks like this: <A.B.C>, e.g. <0.30.0> , but I would like to know what is the meaning of these three "bits": A, B and C.
A seems to be always 0 on a local node, but this value changes when the Pid's owner is located on another node.
Is it possible to directly send a message on a remote node using only the Pid? Something like that: <4568.30.0> ! Message, without having to explicitly specify the name of the registered process and the node name ( {proc_name, Node} ! Message)?
Printed process ids < A.B.C > are composed of 6:
A, the node number (0 is the local
node, an arbitrary number for a remote node)
B, the first 15 bits of the process number (an index into the process table) 7
C, bits 16-18 of the process number (the same process number as B) 7
Internally, the process number is 28 bits wide on the 32 bit emulator. The odd definition of B and C comes from R9B and earlier versions of Erlang in which B was a 15bit process ID and C was a wrap counter incremented when the max process ID was reached and lower IDs were reused.
In the erlang distribution PIDs are a little larger as they include the node atom as well as the other information. (Distributed PID format)
When an internal PID is sent from one node to the other, it's automatically converted to the external/distributed PID form, so what might be <0.10.0> (inet_db) on one node might end up as <2265.10.0> when sent to another node. You can just send to these PIDs as normal.
% get the PID of the user server on OtherNode
RemoteUser = rpc:call(OtherNode, erlang,whereis,[user]),
true = is_pid(RemoteUser),
% send message to remote PID
RemoteUser ! ignore_this,
% print "Hello from <nodename>\n" on the remote node's console.
io:format(RemoteUser, "Hello from ~p~n", [node()]).
For more information see: Internal PID structure,
Node creation information,
Node creation counter interaction with EPMD
If I remember this correctly the format is <nodeid,serial,creation>.
0 is current node much like a computer always has the hostname "localhost" to refer to itself. This is by old memory so it might not be 100% correct tough.
But yes. You could build the pid with list_to_pid/1 for example.
PidString = "<0.39.0>",
list_to_pid(PidString) ! message.
Of course. You just use whatever method you need to use to build your PidString. Probably write a function that generates it and use that instead of PidString like such:
list_to_pid( make_pid_from_term({proc_name, Node}) ) ! message
Process id < A.B.C > is composed of:
A, node id which is not arbitrary but the internal index for that node in dist_entry. (It is actually the atom slot integer for the node name.)
B, process index which refers to the internal index in the proctab, (0 -> MAXPROCS).
C, Serial which increases every time MAXPROCS has been reached.
The creation tag of 2 bits is not displayed in the pid but is used internally and increases every time the node restarts.
The PID refers to a process and a node table. So you can only send a message directly to a PID if it is known in the node from which you do the call.
It is possible that this will work if the node you do the call from already knows about the node on which the process is running.
Apart from what others have said, you may find this simple experiment useful to understand what is going on internally:
1> node().
nonode#nohost
2> term_to_binary(node()).
<<131,100,0,13,110,111,110,111,100,101,64,110,111,104,111,
115,116>>
3> self().
<0.32.0>
4> term_to_binary(self()).
<<131,103,100,0,13,110,111,110,111,100,101,64,110,111,104,
111,115,116,0,0,0,32,0,0,0,0,0>>
So, you can se that the node name is internally stored in the pid. More info in this section of Learn You Some Erlang.