% $Id: readerswriters.erl,v 1.1 2019/12/03 20:23:02 leavens Exp leavens $ -module(readerswriters). -export([start/0, start_read/1,end_read/1,start_write/1,end_write/1, readers/1,writers/1]). %% Client API start_read(ServerPid) -> rpc(ServerPid, start_read). end_read(ServerPid) -> ServerPid ! {self(), end_read}. start_write(ServerPid) -> rpc(ServerPid, start_write). end_write(ServerPid) -> ServerPid ! {self(), end_write}. readers(ServerPid) -> rpc(ServerPid, readers). writers(ServerPid) -> rpc(ServerPid, writers). %% Helping functions rpc(Pid, Msg) -> Pid ! {self(), Msg}, receive {Pid, Reply} -> Reply end. %% Server start() -> spawn(fun() -> init() end). init() -> loop(0, 0). % State is the number of readers and the number of writers. % Invariant is that (Readers >= 0 andalso Writers >= 0 % andalso (Readers > 0 ==> Writers == 0) % andalso (Writers > 0 ==> Writers == 1 andalso Readers == 0) loop(Readers, Writers) -> receive {Pid, start_read} when Writers =:= 0 -> Pid ! {self(), ok}, loop(Readers+1, Writers); {_Pid, end_read} -> loop(max(0,Readers-1), Writers); {Pid, start_write} when Writers =:= 0, Readers =:= 0 -> Pid ! {self(), ok}, loop(Readers, Writers +1); {_Pid, end_write} -> loop(Readers, max(0, Writers-1)); {Pid, readers} -> Pid ! {self(), Readers}, loop(Readers, Writers); {Pid, writers} -> Pid ! {self(), Writers}, loop(Readers, Writers) end.