Klub grających w Grę liczy N>4 członków i ma salę z S>1 czteroosobowymi stolikami do gry. Partia Gry jest rozgrywana między dwoma parami graczy. Podczas spotkań klubowych 1<2P<N najsilniejszych graczy gra wyłącznie ze swoimi stałymi parnerami, pozostali dobierają się w pary dynamicznie. Stałe pary mają ustalone unikatowe identyfikatory (od 1 do P), pozostali mają identyfikator 0.
Gracz przychodzący na spotkanie klubowe, jeśli ma stałego partnera czeka na niego. Gracz bez stałego partnera tworzy parę z innym pojawiającym się graczem bez stałego partnera.
Aby możliwe było rozpoczęcie rozgrywki muszą być dwie pary graczy i wolny stolik. Rozegranie partii polega na wykonaniu przez każdego z graczy procedury rozgrywam_Grę. Po jej zakończeniu gracze odchodzą od stolika pojedynczo. Stolik staje się wolny, gdy odejdzie od niego ostani gracz.
Korzystając z semaforów binarnych i/lib ogólnych zapisz treść procesu Gracz(id_pary: 0..P).
Rozwiązanie:
type
stolik_stan = {wolny, zajety};
var
ochrona: binary semaphore := 1;
czeka_para: array [1..P] of binary semaphore := P TIMES 0;
liczba_czeka_para: array [1..P] of integer := P TIMES 0;
liczba_par_gotowych: integer := 0;
czeka_dynamiczny: binary semaphore := 0;
liczba_czeka_dynamiczny: integer := 0;
stolik : semaphore := S
stolik_stan: array [1..S] of stolik_stan := S times wolny;
liczba_przy_stoliku: array [1..S] of integer := S times 0;
aktualny_stolik_id: integer;
plan_budzenia: array [1..4] of (reference to) binary semaphore;
ochrona_stolikow: binary semaphore := 1;
process Gracz(id_para: 0..N)
var
stolik_id: integer;
begin
if (id_para=0)
GraczDynamicznyStart();
else
GraczParaStart(id_para);
rozgrywam_Gre();
GraczKoniec();
end;
procedure GraczDynamicznyStart(var stolik_id: integer)
begin
P(ochrona);
if (liczba_par_gotowych>0) and (liczba_czeka_dynamiczny>0) then
begin
P(stolik);
aktualny_stolik_id := rezerwuj_stolik();
para := znajdz_gotowa_pare();
plan_budzenia := { 1 -> czeka_dynamiczny; 2 -> czeka_para[para]; 3 -> czeka_para[para]; 4 -> ochrona; }
P(ochrona_stolikow);
end;
else if (liczba_czeka_dynamiczny>2) then
begin
P(stolik);
aktualny_stolik_id := rezerwuj_stolik();
plan_budzenia := { 1 -> czeka_dynamiczny; 2 -> czeka_dynamiczny; 3 -> czeka_dynamiczny; 4 -> ochrona; }
P(ochrona_stolikow);
end;
else
begin
liczba_czeka_dynamiczny++;
V(ochrona);
P(czeka_dynamiczny);
liczba_czeka_dynamiczny--;
end;
stolik_id := aktualny_stolik_id;
liczba_przy_stoliku[stolik_id]++;
V(plan_budzenia[liczba_przy_stoliku[stolik_id]]);
end;
procedure GraczParaStart(id: 1..N, var stolik_id: integer)
var
para: integer;
begin
P(ochrona);
if (liczba_czeka_para[id]=1 and liczba_czeka_dynamiczny>1) then
begin
P(stolik);
aktualny_stolik_id := rezerwuj_stolik();
para := znajdz_gotowa_pare();
plan_budzenia := { 1 -> czeka_para[id]; 2 -> czeka_para[para]; 3 -> czeka_para[para]; 4 -> ochrona; }
P(ochrona_stolikow);
end;
else if (liczba_czeka_para[id]=1 and liczba_par_gotowych>0)
begin
P(stolik);
aktualny_stolik_id := rezerwuj_stolik();
plan_budzenia := { 1 -> czeka_para[id]; 2 -> czeka_dynamiczny; 3 -> czeka_dynamiczny; 4 -> ochrona; }
P(ochrona_stolikow);
end;
else
begin
liczba_czeka_para[id]++;
if (liczba_czeka_para[id]==2) then
liczba_par_gotowych++;
V(ochrona);
P(czeka_para[id]);
if (liczba_czeka_para[id]==2) then
liczba_par_gotowych--;
liczba_czeka_para[id]--;
end;
stolik_id := aktualny_stolik_id;
liczba_przy_stoliku[stolik_id]++;
if (liczba_przy_stoliku[stolik_id]==4) then
V(ochrona_stolikow);
V(plan_budzenia[liczba_przy_stoliku[stolik_id]]);
end;
procedure GraczKoniec(stolik_id: integer)
begin
P(ochrona_stolikow);
liczba_przy_stoliku[stolik_id]--;
if (liczba_przy_stoliku[stolik_id]=0) then
begin
stan_stolika[stolik_id] := wolny;
V(stolik);
end;
V(ochrona_stolikow);
end;