program processus4; #include "classes/gui.inc" (* czytelnicy pisarze *) unit elem : class; var ile , nr : integer,qui:pi; (*nr procesu ktory zostawil informacje lub ostatni FreePl w buforze*) end elem; unit ecran : GUI process(node:integer); unit outtext : procedure(x,y:integer, s:string); begin call GUI_clearArea(x,y,80,16); call GUI_writeText(x,y,unpack(s),c_black,c_LightGrey); end outtext; unit outmessage: procedure(x,y:integer, s: string); begin call GUI_clearArea(x,y,80,16); call GUI_writeText(x,y,unpack(s),c_lightgrey,c_red); end outmessage; unit circle: procedure(col,x,y,r : integer); begin call GUI_Ellipse(x,y,r,r,0,360,c_black,col); end circle; unit line : procedure(col,x,y,dlugosc:integer,poziomo:boolean); begin call GUI_move(x,y); (* pozycja linii *) if poziomo then call GUI_LineTo(x+dlugosc,y,col); else (* linia pionowa *) call GUI_LineTo(x, y+dlugosc,col); fi; end line; unit Fin: procedure; begin call endRun end fin; unit pisarz: procedure(nr:integer); (*nr jest jednoczesnie numerem kolorem wlasnym i numerem pisarza*) begin call GUI_Ellipse((nr-1)*150+20,8,10,10,0,360,c_black,nr); call GUI_WriteText((nr-1)*150+50,5,unpack("Author"),c_black,c_white); call GUI_WriteInt((nr-1)*150+30,5,nr,nr,c_white); call GUI_rect((Nr-1)*150+10,20,(nr-1)*150+ 110,200,c_black,c_lightgrey); end pisarz; unit magazyn : procedure(posX,posY : integer); begin call GUI_Rect(10,250,600,305, c_Black,c_lightgrey); call outtext(posX,posY-8,"B U F F E R"); call outtext(posX,posY+60,"READERS' QUEUE"); call outtext(posX+ 300, posY+60,"WRITERS'QUEUE"); end magazyn; begin call GUI_clear; return; enable magazyn, pisarz; do accept Fin, line, circle, outtext, outmessage, GUI_Keypressed, GUI_ClearArea od; end ecran; unit pi : elem process(node,nr : integer, M : monitor,ek:ecran); (* nr jest numerem pisarza *) const stala=76;(* dludosc linii rysowanej przez pisarza *) var posX, posY : integer; (* pozycja pisarza na ekranie *) unit tempo : procedure(n:integer); var i : integer; begin for i :=1 to n do i:= i od end tempo; unit wezwij_put : procedure(e:elem); var czekaj : boolean; begin (* najpierw wymazuje z obszaru pisarza *) call ek.outtext((nr-1)*150+20,210,"try to send"); for i := 1 to e.ile do call ek.line(7,(nr-1)*150+22,26+i,stala, true); call tempo(50); od; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); call ek.outtext((nr-1)*150+20,210,"waiting"); do call M.putt(e.nr, e.qui, e.ile, czekaj); if czekaj then call ek.outmessage((nr-1)*150+20,210,"stopped"); stop ; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); else call ek.outtext((nr-1)*150+20,210,"sending"); exit fi; od; end wezwij_put; unit wezwij_get : procedure(inout e:elem); var czekaj : boolean, qui:pi,n,ch:integer ; (*autor chce cos odczytac z magazynu *) begin do n := e.nr; qui := e.qui; call m.gett(n,qui,ch, czekaj); if czekaj then call ek.outmessage((nr-1)*150+20,210,"stopped"); stop ; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); (* magazyn jest zajety; pisarz zostanie wpisany do kolejki oczekujacych*) else e:=new elem; e.nr :=n; e.qui:=qui; e.ile :=ch; call ek.outtext((nr-1)*150+20,210,"receiving"); for i := 1 to ch do call ek.line(n,(nr-1)*150+22,26+i,stala,true); call tempo(100); od; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); (* otrzymalem wiadomosc od pisarza nr *) exit fi; od; end wezwij_get; unit fin : procedure; end; var el: elem, r : real; begin call ek.pisarz(nr); return; do r := random*100; (*if r=0 then accept fin; exit fi; *) (* to niezbt dobre rozwiazanie ze wzgl na kolejnosc *) if r<50 then (* pisarz cos produkuje i chce to wyslac *) el := new elem; el.qui := this pi; el.nr := nr; el.ile := random*170; call ek.outtext((nr-1)*150+20,210,"writing"); for i := 1 to el.ile do call ek.line(nr,(nr-1)*150+22,26+i,stala,true); call tempo(100); od; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); call tempo(100); call wezwij_put(el) else (* pisarz zdecydowal sie cos przeczytac *) el := new elem; el.nr := nr; el.qui := this pi; call ek.outtext((nr-1)*150+20,210,"demanding"); call wezwij_get(el); call ek.GUI_clearArea((nr-1)*150+20,210,80,16); call tempo(100); call ek.outtext((nr-1)*150+20,210,"reading"); (* czytam przesylke *) for i := el.ile downto 1 do call ek.line(7,(nr-1)*150+22,26+i,stala,true); call tempo(50); od; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); fi; od; end pi; unit monitor : elem process(node,size,max_proc : integer, ek:ecran); const posX = 30, posY = 250; unit Belem : class(e:elem,posx:integer); end Belem; var buffer : arrayof Belem, queue_pour_lire, queue_pour_ecrire : queue, Qpos , x,y: integer, counter, ilosc_ak, i, nb_proc: integer; (* zmienna counter mowi ile jest elementow w buforze *) (* ilosc_ak = ilosc miejsca w magazynie juz wykorzystana*) (* nb_proc = ilosc procesow stojacuch w obu kolejkach *) unit qEl: class; var qui : pi, next : qEL; end qEL; unit queue: class(pos:integer); var first, last : qEL; unit into : procedure(p: pi,nr: integer (* nr is the no of pi*)); var aux : qEL, c: integer; begin call ek.circle(nr,pos+30,339,12); pos := pos+30; (* rysowanie kolka w odpowiedniej kolejce i odp.kolorem*) nb_proc := nb_proc+1; aux := new qEL; aux .qui :=p; aux . next := none; if first=none then first := aux; last := aux else last.next := aux; last := aux; fi; end into; unit out : function : pi; begin if first=none then exit else nb_proc := nb_proc -1; call ek.circle(15,pos,339,13); pos :=pos-30; (* wymazanie kolka w odpowiedniej kolejce *) result := first.qui; first := first.next; fi; end out; unit empty : function: boolean; begin result := (first=none) ; end empty; end queue; unit tempo : procedure(n:integer); var j : integer; begin for j := 1 to n do j:= j od; end tempo; unit putt : procedure(nr:integer,qui:pi,ch:integer; output czekaj : boolean); var aux, i : integer,e : elem; begin if (counter< 20 and ilosc_ak+ch 0 then (* mozna cos zabrac z magazynu *) e := buffer(counter).e; nr := e.nr; qui := e.qui; ch := e.ile; counter := counter - 1; czekaj := false; for i := x downto x-ch do call ek.line(7,i,posY+7,39,false); call tempo(100); od; x := x-ch; ilosc_ak := ilosc_ak-ch; (* w magazynie zwolnilo sie miejsce i ktos moze wpisac *) if not queue_pour_ecrire.empty then (* writeln("M budzi pisarza ktory chce pisac ");*) p := queue_pour_ecrire.out; call ek.GUI_clearArea((nr-1)*150+20,210,80,16); resume(p); fi; else (*jezeli counter=0 tzn. nic nie ma w magazynie *) (* writeln("M wpisuje pisarza",nr,"do kolejki czytelnikow");*) czekaj := true; (* qui := p;*) (* to jest instrukcja niepotrzebna *) call queue_pour_lire.into(p,nr); fi; end gett; begin (* tu sie zaczyna tresc monitora *) array buffer dim(1:20); counter := 0; x := 15; ilosc_ak := 0; Qpos := posX; queue_pour_lire := new queue(Qpos); queue_pour_ecrire := new queue(Qpos+300); call ek.magazyn(posX,posY); return; do accept putt, gett; if ek.GUI_KeyPressed<>0 then call ek.fin fi; if nb_proc = max_proc then call ek.outmessage(470,339,"DEADLOCK! press CR"); readln; call ek.fin; fi; od; end monitor; (* M A I N *) var M : monitor, i, j, nbNodes,ile : integer, EK : ecran, EKR : arrayof ecran, PROC : arrayof arrayof pi, p : pi, TABnodes, NbProc : arrayof integer; begin write("The Number of nodes- processors ?: "); readln(NbNodes); writeln(nbNodes); if nbNodes = 0 then call ENDRun fi; array TABnodes dim (1: NbNodes); array NbProc dim (1: NbNodes); ile := 0; for i := 1 to NbNodes do write("Node number ",i, " ? "); readln( TABnodes(i)); writeln; write("Number of Readers/Writers on this node",TABnodes(i)," ? "); readln(NbProc(i)); writeln; ile := ile + NbProc(i); od; array EKR dim (1:NbNodes); for i := 1 to nbNodes do if NbProc(i)>0 then j := TABnodes(i); ek := new ecran(j); EKR(i) := ek; resume(ek) fi; od; (* ile= ilosc utworzonych procesow typu Readaes/writers na wszystkich razem komputerach polaczonych w siec*) (* zakladam, ze pierwszy z uzytych "node" =0 i ma ilosc procesow >0 - to oczywiscie mozna zmienic!!*) ek := EKR(1); M := new monitor(0,600,ile,ek); resume(M); array PROC dim (1: nbNodes); for i := 1 to nbNodes do array PROC(i) dim (1 : NbProc(i)); ek := ekr(i); for j := 1 to NbProc(i) do ile := TabNodes(i); P := new pi(ile,j,M,ek); Proc(i,j) := P; od od; ek := EKR(1); call ek.outmessage(400,440,"press CR"); readln; call ek.outtext(400,440," press any key to STOP "); for i :=1 to NbNodes do for j := 1 to NbProc(i) do p := Proc(i,j); resume(p); od od; end processus4;