blog.michalt.pl

Korutyny w C++ 20

22.12.2020 0:35 Tech

Czas na ostatni i dosyć przykrótki wpis na temat nowości w dwudziestym standardzie języka C++. Oczywiście jest ich więcej, ale wspomnę o nich być może jedynie pokrótce w jednym z następnych wpisów.

Tym razem padło na korutyny, które możecie znać z innych języków programowania. Niestety, aby móc z nich skorzystać i nimi się pobawić trzeba sporo się napocić. Czemu? W bibliotece standardowej brakuje potrzebnych struktur danych. Zatem nie pozostaje nam nic innego jak mozolne pisanie własnych – a to nie jest krótka i przyjemna zabawa, albo skorzystać z gotowego rozwiązania, np. biblioteki cppcoro, którą można znaleźć tu: https://github.com/lewissbaker/cppcoro.


Czym zatem są korutyny? Są to funkcje pozwalające pisać kod sekwencyjny, który działa tak jakby był współbieżny – mamy tu do czynienia z funkcjami przerywalnymi - czyli przerywając jedno zadanie, dajemy możliwość wykonywania się innemu. W skład korutyn wchodzą funkcje asynchroniczne i generatory. Mówiąc o korutynach musimy pamiętać o 3 nowych słowach kluczowych języka: co_yield, co_return i co_await.


Generatory

W C++ działają one co najmniej podobnie jak w innych językach programowania. U konkurencji nie znajdziemy jednak przedrostka ‘co’ przed yield. Generatory pozwalają na wielokrotne zwracanie wartości przez funkcję lub metodę. Jednak każde jej zwrócenie jest przez nas kontrolowane, a co za tym idzie, mamy kontrolę nad przebiegiem sekwencji kodu – od nas może np. zależeć w którym momencie wykona się konkretny przebieg pętli.

korutyny - generatory

W powyższym przykładzie zdefiniowana została funkcja zwracajLiczby, która przy pomocy pętli for daje możliwość zwracania po kolei liczb od 1 do 10. Jednak funkcja za każdym razem zatrzymuje się przy co_yield – dopiero pobranie wartości poprzez strukturę generator, a właściwie wywołanie funkcji getValue zwraca wartość i powoduje następny przebieg pętli.


Funkcje asynchroniczne

Tu na pierwszy plan wychodzą 2 słówka: co_await i co_return. Pierwsze z nich powoduje przerwanie wykonywania funkcji przed której wywołaniem ono się znajduje, aż do momentu w którym funkcja z zwróci wartość przy użyciu co_return. Można by odnieść wrażenie, że co_await w połączeniu z co_return robi to samo co co_yield – no nie do końca - co_yield może zwracać wiele wartości, co_return tylko jedną – reszta jest analogiczna.


Słowem podsumowania

O ile przedstawione tu koncepcje przypadły mi do gustu, o tyle ich wykonanie nie i odnoszę wrażenie, że twórcy standardu popełnili falstart. Brak struktur do korutyn jest dosyć bolesny, a przedrostki co_ w operatorach wyglądają dosyć brzydko. Jeśli tak jak mnie (z powodu ich implementacji) nie przekonały Was korutyny, zawsze pozostają klasyczne wątki – tym akcentem kończę ów wpis.

Do przeczytania! :)