Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -module(lock3).
- -export([init/3]).
- %lock3: Each lock has a unique identifier: 1,2,3,4 which gives the lock a priority.
- %Use of Lamport clocks to give locks in time priority order.
- init(MyId, Nodes, MyClock) -> %when the lock is started it is given a unique ID: MyId
- MyClock = 0, %The initial value of MyClock is zero
- open(Nodes, MyId, MyClock).
- open(Nodes, MyId, MyClock) ->
- receive
- {take, Master} -> %my worker wants the lock
- Refs = requests(Nodes, MyId, MyClock), %inform all other locks that i need to be taken
- wait(Nodes, Master, Refs, [], MyId, MyClock, MyClock); %and enter waiting state (My current clock and my request clock!!!)
- {request, From, Ref, _, Clock} -> %request from another lock
- NewClock = lists:max([MyClock, Clock]) + 1, %update MyClock
- From ! {ok, Ref, NewClock}, %immediately reply ok (i'm in open state)
- open(Nodes, MyId, NewClock); %and enter open state again
- stop ->
- ok
- end.
- requests(Nodes, MyId, MyClock) -> %send a request message to all locks
- lists:map(fun(P) -> R = make_ref(), P ! {request, self(), R, MyId, MyClock}, R end, Nodes). %I send my ID together with the request message.
- wait(Nodes, Master, [], Waiting, MyId, MyClock, _) -> %waiting state with empty list of locks -- all of the locks sent me an ok message!!
- Master ! taken, %the lock is taken
- held(Nodes, Waiting, MyId, MyClock); %enter the held state
- wait(Nodes, Master, Refs, Waiting, MyId, MyClock, MyReqClock) -> %waiting for ok messages
- receive
- %prepei na allaksw to format tou mhnymatos request, wste na periexei kai to Id tou lock apo to opoio erxetai to request!!!
- {request, From, Ref, Req_Id, Req_Clock} ->
- NewClock = lists:max([MyClock, Req_Clock]) + 1, %update MyClock
- if
- MyReqClock > Req_Clock -> %The requesting lock has higher clock priority
- From ! {ok, Ref, NewClock}, %send an ok message to it!
- % NOT back to open state -> back to WAIT state!!!
- wait(Nodes, Master, Refs, Waiting, MyId, NewClock, MyReqClock); %and enter waiting state
- MyReqClock == Req_Clock -> %The req. clock has the same priority as me -> compare process IDs
- if
- MyId < Req_Id -> %The requesting lock has higher priority
- From ! {ok, Ref, NewClock}, %send an ok message to it!
- wait(Nodes, Master, Refs, Waiting, MyId, NewClock, MyReqClock); %and enter waiting state
- true ->
- wait(Nodes, Master, Refs, [{From, Ref}|Waiting], MyId, NewClock, MyReqClock)
- end;
- true -> %I have higher priority: I keep the request and I go on :p
- wait(Nodes, Master, Refs, [{From, Ref}|Waiting], MyId, NewClock, MyReqClock)
- end;
- {ok, Ref, Req_Clock2} -> %i received an ok message from a lock
- NewClock2 = lists:max([MyClock, Req_Clock2]) + 1, %update MyClock
- Refs2 = lists:delete(Ref, Refs), %and I delete it from my list
- wait(Nodes, Master, Refs2, Waiting, MyId, NewClock2, MyReqClock); %waiting for the rest of the ok messages
- release -> %I have to release the lock
- ok(Waiting, MyClock), %I send ok messages to the locks that requested me while I was waiting
- open(Nodes, MyId, MyClock) %back to open state
- end.
- ok(Waiting, MyClock) -> %send ok message
- lists:map(fun({F, R}) -> F ! {ok, R, MyClock} end, Waiting).
- held(Nodes, Waiting, MyId, MyClock) -> %The lock is mine!!!
- receive
- {request, From, Ref, _, Req_Clock} -> %I keep on accepting requests from other locks to send them ok afterwards
- NewClock = lists:max([MyClock, Req_Clock]) + 1, %update MyClock
- held(Nodes, [{From, Ref}|Waiting], MyId, NewClock);
- release -> %release message from the worker -> I have to release the lock
- ok(Waiting, MyClock), %I inform the waiting locks!
- open(Nodes, MyId, MyClock) %back to open state!!
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement