ADA:Problem czytelników i pisarzy
Z Wiki Rafał (ert16) Trójniak
Problem z LAB3, części pierwszej zajęć. Oto zaimplementowany algorytm faworyzujący pisarzy.
Rządzą nim następujące reguły :
- W czytelni może być tylko jeden pisarz
- Do czytelni nie może wejść czytelnik, jeśli oczekuje jakiś pisarz
- W czytelni może być wielu czytelników, ale nie może być z nimi żadnego pisarza
main.adb
with Ada.Text_IO,Ada.Integer_Text_IO; use Ada.Text_IO,Ada.Integer_Text_IO; with czytelnia; use czytelnia; procedure main IS gov_ptr:governor_acc; -- Zarządca czytelniki:array (1..4) of proc; -- gracze begin -- Tworzymy zarządcę gov_ptr := new governor; -- Inicjalizujemy graczy, gra się automatycznie rozpoczyna for i in czytelniki'range loop czytelniki(i).setParams( i, gov_ptr,3); end loop; end;
czytelnia.ads
package czytelnia is -- To zadanie będzie zarządzało dostępem task type governor is entry lock_write(pid :in Integer); entry lock_read(pid : in Integer); entry unlock_read( pid : in Integer); entry unlock_write( pid : in Integer); entry inc( pid : in Integer); entry dec( pid : in Integer); end governor; type governor_acc is Access governor; -- To zadanie będzie próbowało uzyskać dostęp task type proc is entry setParams(si : in Integer;gov : in governor_acc; tries:in Integer); end proc; end czytelnia;
czytelnia.adb
with Ada.Text_IO,Ada.Integer_Text_IO; use Ada.Text_IO,Ada.Integer_Text_IO; package body czytelnia is task body governor is isReaded:Boolean:=false; cnt:Integer:=0; readers : Integer:=0; writer : Boolean:=false; begin Gov_gl : loop select -- Nie blokujemy do pisania, dopuki : -- - nie ma innego piszącego -- - nie ma czytających when readers =0 and writer = false => accept lock_write(pid :in Integer) do -- W czytelni jest teraz pisarz writer:=true; -- Komunikaty put("["); put(pid); put("W]Lock"); new_line; end lock_write; or -- Nie blokujemy do czytania dopuki : -- Kolejka pisarzy nie będzie pusta -- Pisarze nie odblokują czytelni when lock_write'Count =0 and writer = false => accept lock_read(pid : in Integer) do -- W czytelni jest o jeden więcej czytających readers:=readers+1; -- Komunikaty put("["); put(pid); put("R]Lock"); new_line; end lock_read; or -- Jak nie zablokowane do pisania, to nie odblokujemy when writer=true => accept unlock_write( pid : in Integer) do -- W czytelni nie ma piszącego writer:=false; -- Komunikaty put("["); put(pid); put("W]Unlock"); new_line; end unlock_write; or -- Jak nie ma czytających, to nie odblokujemy when readers>0 => accept unlock_read( pid : in Integer) do -- W czytelni jest ojednego więcej czytającego readers:=readers-1; -- Komunikaty put("["); put(pid); put("R]Unlock"); new_line; end unlock_read; or -- Zliczamy ilość uczestników accept inc( pid : in Integer ) do cnt:=cnt+1; end inc; or -- Zliczamy ilość uczestników accept dec( pid : in Integer) do cnt:=cnt-1; end dec; end select; -- Jeśli niema uczestników, to kończymy exit Gov_gl when cnt=0 ; end loop Gov_gl; end governor; task body proc is id:Integer; govern:governor_acc; tri:Integer; isWriter:Boolean:=false; begin accept setParams(si :in Integer;gov :in governor_acc; tries:in Integer) do tri:=tries; id:=si; govern:=gov; if id <= 2 then isWriter:=true; end if; -- Rejestrujemy się do zabawy govern.inc(id); -- Komunikaty put("[");put(id);if isWriter then put("W");else put("R");end if; put("]Narodzony proces"); new_line; end setParams; -- Rozpoczynamy serię prób while tri>0 loop -- CZekamy pomiędzy próbami delay Duration(id)/10; -- Komunikat put("[");put(id);if isWriter then put("W");else put("R");end if; put("] Proces czeka"); new_line; -- Staramy się uzyskać blokadę if isWriter then govern.lock_write(id); else govern.lock_read(id); end if; -- Czekamy po uzyskaniublokady delay Duration(id)/10; -- Zwalniamy blokadę if isWriter then govern.unlock_write(id); else govern.unlock_read(id); end if; -- Zmniejszamy ilość pozostałych prób tri:=tri-1; end loop; -- Rezygnujemy z zabawy govern.dec(id); -- Komunikat put("["); put(id);if isWriter then put("W");else put("R");end if; put("]Proces umiera"); new_line; end; end czytelnia;