Programowanie współbieżne i rozproszone/PWR Ćwiczenia 5

From Studia Informatyczne

Producenci i konsumenci

Zadanie

Napisz w CSP rozwiązanie problemu producentów i konsumentów z jednym producentem, jednym konsumentem i jednym buforem jednoelementowym.

[  PRODUCENT:: p: porcja;
    *[true -> produkuj(p);
              BUFOR!p
     ]
|| KONSUMENT:: p: porcja;
    *[BUFOR?p -> konsumuj(p)
     ]
|| BUFOR:: p: porcja;
    *[PRODUCENT?p -> KONSUMENT!p
     ]
]
Zadanie

Zmodyfikuj powyższe rozwiązanie tak, aby było wielu producentów.

[  PRODUCENT(i: 1..N):: p: porcja;
    *[true -> produkuj(p);
              BUFOR!p
     ]
|| KONSUMENT:: p: porcja;
    *[BUFOR?p -> konsumuj(p)
     ]
|| BUFOR:: p: porcja;
    *[(i: 1..N)PRODUCENT(i)?p -> KONSUMENT!p
     ]
]
Zadanie

Zmodyfikuj rozwiązanie pierwszego zadania tak, aby był 1 producent i wielu konsumentów.

[  PRODUCENT:: p: porcja;
    *[true -> produkuj(p);
              BUFOR!p
     ]
|| KONSUMENT(i: 1..K):: p: porcja;
    BUFOR!Chce(); 
    *[BUFOR?p -> konsumuj(p); BUFOR!Chce()
     ]
|| BUFOR:: p: porcja;
    *[PRODUCENT?p -> [(i:1..K)KONSUMENT(i)? Chce() -> KONSUMENT(i)!p]
     ]
]
Zadanie

Napisz rozwiązanie problemu producentów i konsumentów z wieloma producentami, wieloma konsumentami i jednym M elementowym buforem cyklicznym.

[  PRODUCENT:: p: porcja;
   *[true -> produkuj(p);
             BUFOR!p
    ]
|| KONSUMENT:: p: porcja;
   *[true -> BUFOR!chcę();
             BUFOR?p;
             konsumuj(p)
    ]
|| BUFOR:: bufor: (0..M-1) porcja;
   pozycja, ile: integer;
   (pozycja, ile) := (0,0);
   *[ile < M; PRODUCENT?bufor((pozycja + ile) mod M) ->
        ile := ile + 1
    |ile > 0; KONSUMENT?chcę() -> KONSUMENT!bufor(pozycja);
                                  ile := ile - 1;
                                  pozycja := (pozycja + 1) mod M
    ]
]

Czytelnicy i pisarze

Zadanie

Rozwiąż problem czytelników i pisarzy. Wykorzystaj w pełni synchroniczność mechanizmu CSP, unikając przesyłania potwierdzeń, gdy tylko jest to możliwe.

[  CZYTELNIK(i:1..C)::
   *[true -> CZYTELNIA!czytam();
             czytanie();
             CZYTELNIA!koniec_czytania()
    ]
|| PISARZ(i:1..P)::
   *[true -> CZYTELNIA!chcę_pisać();
             CZYTELNIA?możesz_pisać();
             pisanie();
             CZYTELNIA!koniec_pisania()
    ]
|| CZYTELNIA:: czyt: integer;
   comment  czyt - liczba czytaj±cych czytelników
   czyt := 0;
   *[(i:1..C) CZYTELNIK(i)?czytam() -> czyt := czyt + 1
    |(i:1..C) CZYTELNIK(i)?koniec_czytania() ->
         czyt := czyt - 1
    |(i:1..P) PISARZ(i)?chcę_pisać() ->
        *[(j:1..C) czyt > 0; CZYTELNIK(j)?koniec_czytania() ->
              czyt := czyt - 1
         ];
        PISARZ(i)!możesz_pisać();
        PISARZ(i)?koniec_pisania();
    ]
]

Turniej =

Zadanie

W systemie działa arbiter i szesnastu graczy. Arbiter łączy graczy w pary zgodnie z kolejnością zgłoszeń, a następnie informuje kto z kim gra. Gra polega na wymianie losowych liczb (funkcja {\tt losuj()}). Wygrywa ten z graczy, który podał większą liczbę, w przypadku równych wartości wygrywa gracz o większym numerze. Zwycięzca przechodzi do następnej tury i zgłasza się ponownie do arbitra. W danej chwili mogą toczyć się rozgrywki w kilku turach. Po zakończeniu rozgrywek arbiter ogłasza zwycięzcę i rozpoczyna się nowa rozgrywka.


[  ARBITER:: zgłoszenie:(1..4) integer;
   tura, i: integer;
   *[(j:1..4) zgłoszenie(j) <> -1 -> zgłoszenie(j) := -1];
   *[(j:1..16) GRACZ(j)?tura ->
       [tura < 5 ->
           [zgłoszenie(tura) <> -1 ->
               [(k:1..16) k = zgłoszenie(tura) ->
                   GRACZ(k)!j;
                   GRACZ(j)!k;
                   zgłoszenie(tura) := -1
               ]
           |zgłoszenie(tura) = -1 -> zgłoszenie(tura) := j
           ]
       |tura = 5 -> i := 1;
           *[(k:1..16) k = i -> GRACZ(k)!wygrał(j); i := i + 1]
       ]
   ]
|| GRACZ(i:1..16):: gra: boolean;
   przeciw, tura, pom, wynik: integer;
   comment pom i wynik służ± do zapamiętania wylosowanych liczb
           gra oznacza czy już przegrali¶my w danej rozgrywce
   *[true -> (tura, gra) := (1, true);
       *[gra; tura < 5 -> ARBITER!tura;
           ARBITER?przeciw;
           pom := losuj();
           [i > przeciw ->
               [(j:1..16) j = przeciw ->
               GRACZ(j)!pom;
               GRACZ(j)?wynik;
               ];
               [wynik <= pom -> tura := tura + 1
               |wynik > pom -> gra := false
               ]
           |i < przeciw ->
               [(j:1..16) j = przeciw ->
               GRACZ(j)?wynik;
               GRACZ(j)!pom;
               ];
               [wynik < pom -> tura := tura + 1
               |wynik >= pom -> gra := false
               ]
           ]
       ];
       [tura < 5 -> ARBITER?wygrał(pom)
       |tura = 5 -> ARBITER!tura;
           ARBITER?wygrał(pom)
       ]
   ]
]