threads

Wątki w SFML (threads)

Czym są wątki?


Zgodnie z definicją wątki to najmniejsza dla której można zarezerwować czas procesora, dodajmy że na komputerach może działać wiele programów jednocześnie. W praktyce wygląda to w ten sposób, że komputer wykonuje przez chwilę instrucje jednego programu zatrzymuje go i wykonuje polecenia kolejnego, później wraca z powrotem do pierwszego i kontynuuje jego działanie. Całość wykonywana jest bardzo szybko i dzięki temu mamy wrażenie, że wiele aplikacji wykonuje się jednocześnie w tym samym czasie.

Standardowo nasz program składa się się z jednego wątku (main thread), jednak czasami może się zdarzyć, że nasz program będzie musiał wykonać bardzo obciążające lub wymagające dużo czasu instrukcje i  wtedy moglibyśmy zauważyć zawieszenie programu. W tym wypadku przychodzi nam z pomocą wielowątkowość, dzięki której możemy „zrzucić” np. wczytywanie danych do osobnego wątku i „jednocześnie” wyświetlić np. ekran ładowania.

 

sf::Threads vs std::threads


Preferowanymi wątkami są te wprowadzone to standardu c++11, dlatego jeżeli posiadasz IDE zgodne z tym standardem korzystaj z nich. Te w SFML’u powstały, ponieważ gdy wydawano SFML 2.0 nie było wątków w standardzie C.

 

Tworzenie wątku z użyciem SFML


Z racji, że ten kurs dotyczy SFML’a pokaże cie jak korzystać wątków w nim zawartych, a jest ono proste. Odsyłam cię także do dokumentacji sf::Threads.

Efekt działania widzimy poniżej:

Widzimy na screenie sposób w jaki działają wątki, tylko że jak zauważyłeś na przykładzie powyżej tamta funkcja nie miała żadnych argumentów. Utrudnijmy to nieco:

Funkcja, która nie należy do żadnej klasy z jednym argumentem

Należąca do klasy:

Funktor (funkcja-obiekt)

Ostatni przykład używający funktora jest najciekawszy, ponieważ pokazuje że sf::Threads może przyjąć każdy rodzaj funkcji, które nie są bezpośrednio obsługiwane. Ta cecha jest szczególnie ciekawa przy c++11 lambda czy std::bind.

Jeżeli chcesz użyć sf::Threads w środku klasy nie zapomnij, że ma własny domyślny konstruktor. Wtedy musisz skorzystać z listy inicjalizacyjnej:

Jeżeli potrzebujesz, aby twój obiekt powstał najpierw możesz opóźnić użycie konstruktora sf::Threads korzystając z operatora new.

 

Uruchamiania/zatrzymywanie pauzowanie wątków


 Uruchamianie, które już widzieliśmy wygląda następująco:

W konstruktorze podajemy naszą funkcję, która ma zostać uruchomiona podczas działania wątku, a następnie ją zdalnie uruchamiamy.

Może się zdarzyć, że z jakiegoś powodu musimy zatrzymać działanie wątku, możemy to zrobić w taki sposób:

Jednak musisz pamiętać, że wait() uruchamia destruktor i w tym momencie nasz wątek przestaje istnieć i nie możemy go już wskrzesić.

Może się zdarzyć, że musimy wstrzymać działanie wątku na jakiś czas, jednak w sf::Threads nie ma takiej funkcji która by to pozwalała, jedyny sposób aby wstrzymać działanie wątku to sf::sleep. Podczas jej działania program nie zużywa CPU.

 

MUTEX


Jak pewnie zauważyłeś w pierwszym przykładzie w konsoli tekst został wypisany w sposób chaotyczny, a może się zdarzyć że działanie dwóch wątków może powodować błędy krytyczne i dlatego korzysta się z mutex’ów. Więcej o czym są mutex’y znajdziesz TUTAJ.

Dodam jeszcze, że mogą się one przydać przy wczytywaniu mapy, załóżmy że  w jednym wątku wczytujemy obrazki, a w drugim wyświetlamy planszę. Może się zdarzyć, że będziemy próbowali ją wyświetlić, mimo że jeszcze nie zdążyliśmy wczytać wszystkich tekstur co oczywiście spowoduje niezbyt ciekawy efekt.

Oryginalny artykuł