Dzielenie pasma łącza

Łącze internetowe jest dzielone między wielu użytkowników. Szerokość pasma wynosi N. Użytkownik chcąc korzystać z łącza, rezerwuje potrzebną szerokość (potrzebna_szerokosc>0 i potrzebna_szerokosc<=N) pasma. Użytkonik zwalnia zarezerwowaną szerokość pasma, gdy skończy z niego korzystać. Zsynchronizuj użytkowników, aby mogli korzystać z połączenia zgodnie ze swoimi potrzebami.

const 
  N = ...;
  LICZBA_UZYTKOWNIKOW = ...;

procedure rezerwacja_pasma(szerokosc_dla_uzytkownika: integer)
begin
...
end;

procedure zwalnianie_pasma(szerokosc_dla_uzytkownika: integer)
begin
...
end;

process Uzytkownik(i: integer)
var
  szerokosc_dla_uzytkownika: integer;
begin
  while (true) do
  begin
    wlasne_sprawy();
    szerokosc_dla_uzytkownika := losuj(1, N);
    rezerwacja_pasma(szerokosc_dla_uzytkownika);
    korzystanie_z_lacza();
    zwalnianie_pasma(szerokosc_dla_uzytkownika);
  end;
end;

var
  i: integer;
begin
  cobegin for i:=1 to LICZBA_UZYTKOWNIKOW do begin Uzytkownik(i); end; coend;
end;

Rozwiązanie poprawne

Do rozwiązania tego problemy można wykorzystać metodę Pojedynczego Przetwarzania Żądań. Przetwarzanie żadania rezerwacji opakowujemy semaforem binarnym, w ten sposób przetwarzamy pojedynczo żądania.

var
  szerokosc_niezarezerwowana: integer := N;
  szerokosc_potrzebna: integer := -1;
  rozpatrywanie_rezerwacji_pojedynczo: binary semaphore := 1;
  czekajacy_uzytkownik: binary semaphore := 0;
  ochrona: binary semaphore := 1;

procedure rezerwacja_pasma(szerokosc_dla_uzytkownika: integer)
begin
  P(rozpatrywanie_rezerwacji_pojedynczo);
  P(ochrona);
  if (szerokosc_dla_uzytkownika<szerokosc_niezarezerwowana) then
    begin
      szerokosc_potrzebna := szerokosc_dla_uzytkownika;
      V(ochrona);
      P(czekajacy_uzytkownik);
      P(ochrona);
    end;
  szerokosc_niezarezerwowana := szerokosc_niezarezerwowana - szerokosc_dla_uzytkownika;
  V(ochrona);
  V(rozpatrywanie_rezerwacji_pojedynczo); 
end;

procedure zwalnianie_pasma(szerokosc_dla_uzytkownika: integer)
begin
  P(ochrona);
  szerokosc_niezarezerwowana := szerokosc_niezarezerwowana + szerokosc_dla_uzytkownika;
  if (szerokosc_potrzebna<>-1 and szerokosc_niezarezerwowana>=szerokosc_potrzebna) then
  begin
    szerokosc_potrzebna:=-1;
    V(czekajacy_uzytkownik);
  end;
  V(ochrona);
end;