Since few days, I'm learning Erlang, using the great book Programming Erlang by Joe Armstrong.
I'm following the chapter about concurrent programming, and, at the end of chapter, there's a little problem to solve:
Write a function start(AnAtom, Fun) to register AnAtom as spawn(Fun). Make sure your program works correctly in the case when two parallel processes simultaneously evaluate start/2. In this case, you must guarantee that one of these processes succeeds and the other fails.
I solved the first part of this problem, making sure that each process will be spawned with a different atom.
About the second part, I'm stuck because, if I understood correctly, I cannot find a way to check if two parallel processes evaluate simultaneously the function start/2
. At first, I thought about a counter checking the number of spawns of the process, but I'm not able to understand how to perform this check. I found something interesting here in this thread (coming from an OOP background, I thought about the Singleton pattern), but I'm not sure if reading and writing a file with a counter is the best way to perform this check. I think there's a simple way to do that.
The code I wrote is below:
-module(probl).
-export([start/2,stop/1]).
start(Atom,Fun) ->
% check here counter value
case isUniqueProcess(Times) of % here I'm trying to use a counter, but I'm stuck..
true ->
Pid = spawn(fun() -> doSomething(Atom,Fun) end),
register(Atom,Pid);
false ->
io:format("Sorry, no more processes to spawn."),
void
end.
stop(Atom) ->
case whereis(Atom) of
undefined -> void;
Pid -> io:format("Stopped."), Pid ! stop
end.
isUniqueProcess(Times) -> % here I should increment the counter, but how?
if
Times =:= 0 ->
true;
Times > 0 ->
false
end.
doSomething(Atom,Fun) ->
receive
stop -> void
after 15000 ->
Fun(),
doSomething(Atom,Fun)
end.
For me, coming from a strong OOP background, it's not so easy to switch another programming mindset, like it happens in Erlang, and maybe this is the reason of my difficulties. How can I solve this problem?
You can try this code.
Using rvirding approach:
Or alternatively:
If both, or more processes, try to register under the same name then only the first one will succeed. The following will generate an error when they try to register. Wouldn't be enough just to let the subsequent processes crash in that case? To do this the registering must be done in the started process itself.
If you don't want to crash the process the you could wrap the process in a catch and terminate and explicitly terminate it using
exit(normal)
.