Treść #
Twoim zadaniem jest przygotowanie zestawu wątków oczekujących na funkcje do wykonania. W przeciwieństwie do tworzenia wątków na żądanie pula wątków alokuje wątki robocze (tzw. worker threads) na początku uruchomienia programu i czekają one na sygnał wykonania pracy. Następnie z innych wątków można przekazać funkcję do wykonania przez jeden wątek z puli.
Na tym laboratorium pula wątków powinna implementować 3 funkcje:
initialize
– w ramach puli wątków tworzone jestN
wątków.dispatch
– do wątku oczekującego na prace należy przekazać wskaźnik na funkcję o sygnaturzevoid (*work_function)(void*)
oraz argumenty wywołania. Jeżeli nie ma wolnego wątku do wykonania pracy funkcjadispatch
powinna blokować do czasu znalezienia wolnego wątku.cleanup
– funkcja powinna czekać na skończenie wszystkich worker threads i wykonać funkcjejoin
. Niedopuszczalne jest przerwanie pracy wątku, który przyjął dyspozycję do wykonania funkcji.
Pracę wątku roboczego można opisać w następujących krokach:
Czekaj na zmiennej warunkowej na pracę zleconą z innego wątku (jedna zmienna warunkowa dzielona między wszystkie wątki robocze).
Po przejęciu funkcji roboczej i argumentów wykonania poinformuj, że to się stało. W przeciwnym wypadku uzyskamy wyścig, który spowoduje niestabilną pracę puli wątków.
Wywołaj funkcję z otrzymanymi argumentami.
Powtarzaj do czasu jak nie została wywołana funkcja
cleanup
na puli wątków.
W celu użycia puli wątków została zaimplementowana funkcja obliczania
pola koła metodą monte carlo. Procedura składa się z dwóch dwóch części:
losowania punktów oraz uśredniania uzyskanych wyników. Implementacja
przy użyciu naszej puli wątków realizuje powyższe części jako dwie różne
funkcje robocze: circle_monte_carlo
oraz accumulate_monte_carlo
.
Funkcja accumulate_monte_carlo
musi rozpocząć uśrednianie wyników
dopiero po zakończeniu wszystkich circle_monte_carlo
. Twoim zadaniem w
ramach tego laboratorium będzie zsynchronizowanie tych dwóch funkcji
(bariera nadaje się idealnie do tego celu) oraz przekazanie do nich
prawidłowych danych.
Dla ułatwienia testowania programu w ramach kodu startowego masz do dyspozycji interfejs CLI:
enter command
1. circle <n> <r> <s>
2. hello <n>
3. exit
Umożliwia on wybranie polecenia odpowiednim numerem i przekazanie
argumentów po spacji. Pierwszym poleceniem jest uruchomienie procedury
obliczającej pole koła o promieniu r
wykorzystując n
wątków
losujących w sumie s
próbek. Drugie polecenie uruchamia n
funkcji
testowych wypisujących Hello world from worker n!
. Przy wybraniu
trzeciej opcji program się zamyka czekając na zakończenie wszystkich
zleconych poleceń.
Podpowiedź: Dla ułatwienia zadania ważne miejsca w kodzie, gdzie w
danym etapie należy coś dopisać zostały oznaczone komentarzem
TODO STAGE-X
.
Etapy:
- Zaimplementuj funkcję
initialize
. Utworzonę watki wypisują swójTID
i czekają na zmiennej warunkowej. - Zaimplementuj funkcje
dispatch
. Opcjahello
powinna działać na tym etapie. - Zaimplementuj przekazanie
danych do obliczenia pola koła oraz synchronizację z wątkami losującymi.
Opcja
circle
powinna działać na tym etapie. - Zaimplementuj funkcje
cleanup
. - Program powinien czekać na zakończenie obliczeń i prawidłowo
kończyć wszystkie wątki przy wybraniu opcji
exit
.