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
falseaby 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
makea 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)).