-module(tupleServer). -export([start/0,pipe/2,in/2,in/3,out/2,out/3,rd/2,rd/3, main/0,main2/1, getTime/0]). start() -> tupleServer([],[]). tupleServer(L,RequestL) -> receive {out,E,Time} -> T=getTime(), case checkExistingRequests(RequestL,E) of {noMatch,RequestL1} -> tupleServer([{E,addTime(T,Time)}|L],RequestL1); {match,keep,RequestL1} -> tupleServer([{E,addTime(T,Time)}|L],RequestL1); {match,omit,RequestL1} -> tupleServer(L,RequestL1) end; {stop,Client} -> case lists:splitWith(fun({_,_,C,_}) -> C==Client end,RequestL) of {[],Reqs} -> tupleServer(L,RequestL); {OwnReqs,Reqs} -> Client!{requestRemoved,self()}, tupleServer(L,Reqs) end; {InRd,F,Time,Client} -> T=getTime(), case lists:member(InRd,[in,rd]) of true -> case lookupIn(InRd,F,L,Client) of {noMatch,L1} -> tupleServer(L1,[{InRd,F,Client,addTime(T,Time)}| RequestL]); {match,L1} -> tupleServer(L1,RequestL) end; false -> tupleServer(L,RequestL) end end. lookupIn(_,_,[],_) -> {noMatch,[]}; lookupIn(Kind,F,[{E,T}|Es],Client) -> case past(T) of false -> case lookupIn(Kind,F,Es,Client) of {noMatch,Es1} -> case catch F(E) of {'EXIT',_} -> {noMatch,[{E,T}|Es1]}; Match -> Client!{tupleMatch,self(),Match}, {match,case Kind of in -> Es1; rd -> [{E,T}|Es1] end} end; {match,Es1} -> {match,[{E,T}|Es1]} end; true -> lookupIn(Kind,F,Es,Client) end. checkExistingRequests([],_) -> {noMatch,[]}; checkExistingRequests([{Kind,F,Client,T}|FCs],E) -> case past(T) of false -> case checkExistingRequests(FCs,E) of {noMatch,FCs1} -> case catch F(E) of {'EXIT',_} -> {noMatch,[{Kind,F,Client,T}|FCs1]}; Match -> Client!{tupleMatch,self(),Match}, {match,case Kind of in -> omit; rd -> keep end, FCs1} end; {match,KO,FCs1} -> {match,KO,[{Kind,F,Client,T}|FCs1]} end; true -> checkExistingRequests(FCs,E) end. out(Space,E) -> Space!{out,E,infinity}. out(Space,E,Time) -> Space!{out,E,Time}. in(Space,F) -> req(in,Space,F,infinity). in(Space,F,Time) -> req(in,Space,F,Time). rd(Space,F) -> req(rd,Space,F,infinity). rd(Space,F,Time) -> req(rd,Space,F,Time). req(Type,Space,F,Time) -> Space!{Type,F,Time,self()}, receive Result -> Result after secondsToMs(Time) -> Space!{stop,self()}, receive {tupleMatch,Space,Match} -> Match; {requestRemoved,Space} -> timeOut end end. getTime() -> TimeStr = os:cmd('date +%s'), case io_lib:fread("~d",TimeStr) of {ok,[Time],_} -> Time; _ -> exit('ivalide time') end. addTime(T1,infinity) -> infinity; addTime(infinity,T2) -> infinity; addTime(T1,T2) -> T1+T2. secondsToMs(infinity) -> infinity; secondsToMs(T) -> 1000*T. past(infinity) -> false; past(T1) -> T1 Space=spawn(tupleServer,start,[]), spawn_link(tupleServer,main2,[Space]), X=rd(Space,fun(E)->f(E) end,1), io:format("Res1: ~w ~n",[X]), X1=in(Space,fun(E)->f(E) end,infinity), io:format("Res2: ~w ~n",[X1]), X2=rd(Space,fun(E)->f(E) end,1), io:format("Res3: ~w ~n",[X2]). main2(Space) -> %timer:sleep(2000), out(Space,{hello,3,4},infinity), io:format("Sent: ~w with Timeout ~w~n",[{hello,3,4},infinity]), timer:sleep(2000), out(Space,{hello,5,6},1), io:format("Sent: ~w with Timeout ~w~n",[{hello,5,6},1]). %f(E) -> {hello,_,_}=E. f({hello,X,Y}) -> {X,Y}.