Gracze

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;