Going through Programming Erlang, encountered this exercise problem in Section 8.11:
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.Here is my first solution, and it seems to compile and run.
Now, is there race condition in the above? I mean, consider Processes A and B both executing start/2:-module(register_function).
-export([start/2]).
start(AnAtom, Fun) ->
case whereis(AnAtom) of
undefined -> register(AnAtom, spawn(Fun));
_ -> error
end.
- Process A calls whereis(AnAtom) which evaluates to 'undefined';
- Process B calls whereis(AnAtom) which evaluates to 'undefined';
- Process A calls register(AnAtom, spawn(Fun)), which succeeds and returns true;
- Process B calls register(AnAtom, spawn(Fun)), which fails as AnAtom has been registered
Ironically, the problem seems to be because presumably register puts AnAtom in some "global" table. Exactly the kind of concurrency problem that Erlang tries to avoid.
How would this be solved? Here is an idea:
- Create a "register_function" server;
- start/2 sends a message to this server with AnAtom and Fun as contents
- presumably the server processes one message at a time and the code between matching a message and executing some expressions is atomic with respect to other messages to the same server
No comments:
Post a Comment