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;
Osobiste