Przetwarzanie

W systemie działają dwa typy procesów: Klient i Pracownik. W systemie dostępny jest monitor Biuro. Klient umieszcza zadanie w monitorze Biuro. Pracownik przetwarza zadanie i zostawia rezultat tej pracy w monitorze Biuro. Klient odbiera rezultat. Procesy w nieskończonej pętli powtarzają te czynności.

monitor Biuro;

type
zadanie_t = ...;
rezultat_t = ...;

export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t);

export procedure przetwarzanie();

process Klient
var 
  zadanie: zadanie_t;
  rezultat: rezultat_t;
begin
  while (true) do
  begin
    zadanie = przygotowanie_zadania(); 
    Biuro.zlecenie_przetwarzania(zadanie, rezultat);
    przetwarzanie_rezultatu(rezultat); 
  end;
end;

process Pracownik
begin
  while (true) do
  begin
    Biuro.przetwarzanie();
  end;
end;

Zsynchronizuj działanie procesów, rozważ warianty:

Jeden klient i jeden pracownik

Przetwarzanie wewnątrz monitora

monitor Biuro;

type
zadanie_t = ...;
rezultat_t = ...;

var
aktualne_zadanie: zadanie_t;
aktualny_rezultat: rezultat_t;
czeka_klient: condition;
czeka_pracownik: condition;

export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t)
begin
  aktualne_zadanie := p_zadanie;
  if (not empty(czeka_pracownik)) then
    signal(czeka_pracownik);
  else {: else jest konieczne - wait nie moze sie zawsze wykonywac :}
    wait(czeka_klient);
  p_rezultat = aktyalny_rezultat;
end;

export procedure przetwarzanie()
begin
  if (empty(czeka_klient)) then
    wait(czeka_pracownik);
  p_rezultat = praca(p_zadanie);
  if (not empty(czeka_klient))
    signal(czeka_klient);
end;

Warto zwrócić uwagę na wykonywanie przez klienta albo instrukcji signal albo instrukcji wait. Gdyby instrukcja wait była wykonywana zawsze to program byłby niepoprawny. W tym przypadku załóżmy, że pracownik czeka na zmiennej czeka_pracownik, przychodzi klient, umieszcze zadanie, budzi pracownika, pracownik natychmiast przejmuje monitor wykonuje zadanie i ponieważ klient nie zdążył wykonać wait na czeka_klient to pracownik nie budzi klienta tylko wychodzi z monitora. Wtedy klient zostaje wznowiony i dopiero wtedy wykonuje wait na czeka_klient. Nastepnie przychodzi pracownik i zauważa że kolejka na zmiennej czeka_klient nie jest pusta więc uznaje, że na zmiennej aktualne_zadanie znajduje się aktualne zadanie (podczas gdy jest to stare, już przetworzone żadanie) i zaczyna je przetwarzać (drugi raz).

Przetwarzanie na zewnątrz monitora

export procedure pobieranie_zadania(out p_zadanie: zadanie_t);

export procedure umieszczanie_rezultatu(in p_rezultat: rezultat_t);

process Pracownik
begin
  while (true) do
  begin
    Biuro.pobieranie_zadania(zadanie);
    rezultat := praca(zadanie);
    Biuro.umieszczanie_rezultatu(rezultat);
  end;
end;

monitor Biuro;

type
zadanie_t = ...;
rezultat_t = ...;

var
aktualne_zadanie: zadanie_t;
aktualny_rezultat: rezultat_t;
czeka_klient: condition;
czeka_pracownik: condition;

export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t)
begin
  aktualne_zadanie := p_zadanie;
  if (not empty(czeka_pracownik)) then
    signal(czeka_pracownik);
  {: nie moze byc else - zawsze musimy czekac :}
  wait(czeka_klient);
  p_rezultat := aktyalny_rezultat;
end;

export procedure pobieranie_zadania(out p_zadanie: zadanie_t)
begin
  if (empty(czeka_klient)) then
    wait(czeka_pracownik);
  p_zadanie := aktualne_zadanie;
end;

export procedure umieszczanie_rezultatu(in p_rezultat: rezultat_t)
begin
  aktualny_rezultat := p_rezultat;
  if (not empty(czeka_klient))
    signal(czeka_klient);
end;

W tym przypadku klient musi wykonać wait na zmiennej czeka_klient zawsze. Gdyby klient postępował tak jak w przypadku przetwarzania wewnątrz monitora to program byłby niepoprawny. Załóżmy, że pracownik czeka na zmiennej czeka_pracownik, przychodzi klient, umieszcza zadanie, budzi pracownika, pracownik natychmiast przejmuje monitor, a następnie wychodzi z monitora. Wtedy zaczyna się wykonywać klient i pobiera rezultat ze zmiennej aktualny_rezultat, ale proces pracownik nie zdążył jeszcze umieścić tam rezultatu.