program processus4; (* 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 :IIUWGRAPH process(node:integer); unit outtext : procedure(x,y:integer, s:string); var A: arrayof char, i: integer; begin call move(x,y); call color(14); (* yellow *) A := unpack(s); for i := lower(A) to upper(A) do (* call HASCII(0); *) call HASCII(ord(A(i))); od; end outtext; unit outmessage: procedure(x,y:integer, s: string); var A: arrayof char, i: integer; begin call move(x,y); call color(12); (* rouge clair *) A := unpack(s); for i := lower(A) to upper(A) do call HASCII(ord(A(i))) od end outmessage; unit circle: procedure(col,x,y,r : integer); var i: integer; begin call color(col); call rectangle(x,y,r,r); for i := 1 to r-1 do call line(col,x,y+i,r,true) od end circle; unit line : procedure(col,x,y,dlugosc:integer,poziomo:boolean); begin call color(col); call move(x,y); (* pozycja linii *) if poziomo then call draw(x+dlugosc,y); else (* linia pionowa *) call draw(x, y+dlugosc); fi; end line; unit Fin:procedure; begin call GrOFF; call endRun end fin; unit pisarz: procedure(nr:integer); begin call color(2*nr+1); call circle(2*nr+1,(nr-1)*150+20,8,10); (* call rectangle((nr-1)*150+20,10,10,10);*) call rectangle((Nr-1)*150+10,20,80,200); end pisarz; unit rectangle:procedure(x,y,dl,wys:integer); var i: integer; begin call move(x,y); call draw(x+dl,y); call draw(x+dl,y+wys); call draw(x,y+wys); call draw(x,y); end rectangle; unit magazyn : procedure; begin call color(1); call rectangle(10,250,600,50); end magazyn; begin call gron(1); return; enable magazyn,pisarz; do accept Fin, line, circle, outtext, outmessage od; end ecran; unit pi : elem process(node,nr : integer, M : monitor,ek:ecran); (* nr jest numerem pisarza *) const stala=62;(* 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,200,"sends "); for i := 1 to e.ile do call ek.line(0,(nr-1)*150+22,32+i,stala, true); call tempo(200); od; call ek.outtext((nr-1)*150+20,200,"waiting "); do call M.putt(e.nr, e.qui, e.ile, czekaj); if czekaj then call ek.outmessage((nr-1)*150+20,180,"stopped"); stop else exit fi; od; end wezwij_put; unit wezwij_get : procedure(inout e:elem); var czekaj : boolean, qui:pi,n,ch:integer ; 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,180,"stopped"); stop else e:=new elem; e.nr :=n; e.qui:=qui; e.ile :=ch; call ek.outtext((nr-1)*150+20,200,"receives"); for i := 1 to ch do call ek.line(2*n+1,(nr-1)*150+22,32+i,stala,true); call tempo(200); od; call ek.outtext((nr-1)*150+20,200, " "); (* 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); call ek.outtext((nr-1)*150+36,8,"Actor"); 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*175; call ek.outtext((nr-1)*150+20,200,"writes "); for i := 1 to el.ile do call ek.line(2*nr+1,(nr-1)*150+22,26+i,stala,true); call tempo(250); od; call ek.outtext((nr-1)*150+20,200," "); call tempo(400); 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,200,"demands "); call wezwij_get(el); call ek.outtext((nr-1)*150+20,200," "); call tempo(500); call ek.outtext((nr-1)*150+20,200,"reads "); (* czytam przesylke *) for i := el.ile downto 1 do call ek.line(0,(nr-1)*150+22,26+i,stala,true); call tempo(250); od; call ek.outtext((nr-1)*150+20,200," "); 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:integer, counter, ilosc_ak, i,x, 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(2*nr+1,pos+30,339,10); 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(0,pos,339,10); 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,x:integer; begin for j := 1 to n do x:=x od; end tempo; unit putt : procedure(n: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(0,i,posY+7,39,false); call tempo(200); 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.outtext((nr-1)*150,180," "); 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 := 12; ilosc_ak := 0; Qpos := posX; queue_pour_lire := new queue(Qpos); queue_pour_ecrire := new queue(Qpos+300); call ek.magazyn; call ek.outtext(posX,posY-6,"BUFFER"); call ek.outtext(posX,posY+60,"READERS' QUEUE"); call ek.outtext(posX+ 300, posY+60,"WRITERS'QUEUE"); return; do accept putt, gett; 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 PROC : arrayof pi,p,P1,P2,P3 : pi, M : monitor, EK : ecran, i, NbProc : integer; begin write("NbProc : "); readln(NbProc); array Proc dim(1:NbProc); ek := new ecran(0); resume(ek); M := new monitor(0,550,NbProc,ek); resume(M); for i := 1 to NbProc do P := new pi(0,i,M,ek); Proc(i) := P; od; call ek.outmessage(550,320,"press CR"); readln; call ek.outtext(550,320," "); for i :=1 to NbProc do p := Proc(i); resume(p); od; end processus4;