Programowanie współbieżne, Laboratorium
Zakładamy, że mamy graf wierzchołków, w którym krawędzie są nieskierowane. Krawędź między wierzchołkami a oznaczamy: . Listę sąsiadów wierzchołka oznaczamy: .
Podobnie jak w poprzednich zadaniach zakładamy, że w grafie istnieje ścieżka Hamiltona złożona z krawędzi postaci (dzięki czemu graf jest spójny), oraz pewna liczba dodatkowych krawędzi (skrótów).
Należy zaimplementować wykonywanie protokołu routingu podobnego do znanego protokołu RIP, zgodnie z poniższymi wskazówkami.
- Każdy wierzchołek zawiera zmienną reprezentującą tzw. routing table (oznaczaną przez ), która dla każdego wierzchołka , różnego od , zawiera następujące dane:
- — wierzchołek ze zbioru (tj. sąsiad ) leżący na najkrótszej, znanej wierzchołkowi , ścieżce od do , oraz
- — długość tej ścieżki .
- Początkowo każdy wierzchołek zna swoich bezpośrednich sąsiadów i wie o istnieniu krawędzi postaci . Zatem,
- dla , początkowo i , a
- dla , oraz
- , jeśli , albo
- , jeśli .
- Ponadto, dla każdego , istnieje flaga (początkowo ustawiona na
true
).- W każdym wierzchołku działają dwa współbieżne wątki:
- oraz
- Oba te wątki mają współbieżny dostęp do routing table . W Go można zaimplementować jako stateful goroutine, a w Adzie jako zmienną protected.
- Co pewien czas budzi się i jeśli istnieją jakieś , gdzie
true
, to tworzy pakiet z ofertą, do którego dodaje pary dla wszystkich takich , ustawiając nafalse
, a następnie wysyła ten pakiet do każdego swojego sąsiada z .- Wątek oczekuje na pakiet z ofertą od jakiegoś sąsiada z . Gdy taki pakiet otrzymuje od jakiegoś sąsiada , to dla każdej pary z takiego pakietu: - wylicza , - jeśli to ustawia nowe wartości: - , - , -
true
,- Oba wątki drukują stosowne komunikaty o wysyłanych i otrzymywanych pakietach oraz zmianach w routing table.
Zwróć uwagę, aby nie blokował dostępu do w czasie, gdy rozsyła pakiet z ofertami do sąsiadów oraz tak zmieniał na
false
aby nie „zagłuszyć” żadnej nowej zmiany.
n
— liczba wierzchołkówd
— liczba dodatkowych krawędzi (skrótów)maxSleep
— odwrotność maksymalnego czasu oczekiwania wątku (maxSleep = 100
oznacza maks. czas. oczekiw. równy 1/100
sekundy)Wszystkie powyższe argumenty powinny być liczbami naturalnymi różnymi od zera.
W celu uruchomienia programu należy wykonać polecenie
go run . ‹n› ‹d› ‹maxSleep›
z uzupełnionymi parameterami będąc w katalogu go
.
Nagranie asciinema
pokazujące przykładowe uruchomienia programu znajduje się w pliku go.cast
.
W celu uruchomienia programu należy go najpierw skompilować poleceniem
make
a następnie wykonać polecenie
./main.bin ‹n› ‹d› ‹maxSleep›
z uzupełnionymi parameterami będąc w katalogu ada
.
Nagranie asciinema
pokazujące przykładowe uruchomienia programu znajduje się w pliku ada.cast
.
Uwaga: w implementacji w Adzie numeracja węzłów wyrażana jest zakresem 1..n
, w przeciwieństwie do Go (0..(n-1)
).