Watki w bibliotece standardowej języka C++

0

Witam

Próbuje się właśnie nauczyć biblioteki thread ale opornie mi to idzie.
O to problematyczny kod.

#include <thread>
void thr()
{
    std::cout << "Powstal watek: " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
    std::cout << std::this_thread::get_id() << " watek zakonczyl dzialanie" << std::endl;
}

int main()
{
    std::cout << "Uruchamiam watek.." << std::endl;
    std::thread th = std::thread( thr );
    std::cout << "Czekam na zakonczenie.." << std::endl;
    try
    {
       /// th.join();
    }
    catch( .../*std::system_error & err */)
    {
       // std::cout << err.what() << std::endl;
    }
    std::cout << "Watek glowny oczekuje 3 sekundy..." << std::endl;
    std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
    std::cout << "Watek glowny oczekuje 2 sekundy..." << std::endl;
    std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
    std::cout << "Watek glowny oczekuje 1 sekunde..." << std::endl;
    std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
    std::cout << "Wynik metody joinable: " << th.joinable() << std::endl;
    ///th.join();
    /// Dlaczego gdy nie wywolam join() i zakoncze aplikacje otrzymuje blad ?
    return EXIT_SUCCESS;
}

Jeżeli chodzi o wątki, mutexy i podobne korzystałem wcześniej z dobrodziejstw biblioteki SFML 2.3.2
W SFMLu obiekt reprezentujący wątek miał następujące metody:
launch() - uruchamia wątek
termiate() - przerwanie wątku
wait() - oczekiwanie na zakończenie wątku
Twórca SFMLa zaleca : ** If you work with compilers that support the new standard and its <thread> header, forget about the SFML thread classes and use it instead -- it will be much better. **

Trudność polega na tym że obsługuje się wątki z biblioteki standardowej inaczej i nie zachowują się tak jak można by się spodziewać.
W kodzie aplikacji zamieszczonym powyżej tworze wątek i każę mu wykonać funkcję thr();
Wyjście programu jest następujące.

Uruchamiam watek..
Czekam na zakonczenie..
Watek glowny oczekuje 3 sekundy...
Powstal watek: 140280658917120
Watek glowny oczekuje 2 sekundy...140280658917120
watek zakonczyl dzialanie
Watek glowny oczekuje 1 sekunde...
Wynik metody joinable: 1
terminate called without an active exception
Przerwane

Dlaczego gdy nie wywołam join() i zakończę aplikacje otrzymuje błąd ?
Teoretycznie wątek powinien się zakończyć....
Co jest przyczyną komunikatu ?:
terminate called without an active exception Przerwane
PS
Jak mogę przerwać wykonanie bieżącego wątku ?
Czy do sprawdzania czy wątek działa służy metoda joinable?
Po co mi metoda detach() - pozwala wątkowi kontynuować wykonanie niezależnie - do czego mogę to wykorzystać ?

4

Jeżeli podczas wywoływania destruktora std::thread wątek jest aktywny (joinable() == true) wtedy wywoływanie jest std::terminate. Innymi słowy: wszystkie wątki "joinable" muszą zostać zakończone (za pomocą .join()), albo aplikacja eksploduje podczas kończenia.

.detach() powoduje, że dany obiekt wątku nie jest już z nim powiązany, tzn. wątek sobie działa "sam" w tle. Sam musisz zadbać o jego poprawne zakończenie przed końcem programu. Jeżeli tego nie zrobisz wybuch jest prawdopodobny.

0

Innymi słowy: wszystkie wątki "joinable" muszą zostać zakończone (za pomocą .join()), albo aplikacja eksploduje podczas kończenia.

join() blokuje aktualny wątek do czasu zakończenia wątku reprezentowanego przez * this
Nie rozumiem czemu wątek musi być zakończony przez join() gdy wątek wykonał funkcję ktora mu zleciłem - sam powienien się zakończyć - taka to moja logika - jest jakiś powód dlaczego tak musi być ?

detach() powoduje, że dany obiekt wątku nie jest już z nim powiązany, tzn. wątek sobie działa "sam" w tle. Sam musisz zadbać o jego poprawne zakończenie przed końcem programu. Jeżeli tego nie zrobisz wybuch jest prawdopodobny.

To znaczy że nie mogę już kontrolować wątku? czy zniszczenie obiektu std::thread nie powoduje zniszczenia wątku wtedy?

2

Nawet jeżeli wątek zakończy działanie (tzn. związana z nim funkcja się zakończy) to i tak będzie on "joinable". Musisz wykonać .join(). Destruktor po prostu to sprawdza i jeżeli okaże się, że .join() nie zostało wykonane od razu jest std::terminate(). Tak to po prostu działa.

Zniszczenie std::thread kiedy wątek jest po .detach() nie powoduje zakończenia wątku. On sobie dalej działa. Kontrolować go możesz - masz do tego przecież różnorodne mechanizmy synchronizacji i przesyłania informacji pomiędzy wątkami. I musisz ich używać, żeby zakończyć wątek - tj. wyjść z jego funkcji przed końcem programu.

Po prostu - musisz dbać o swoje wątki. :-)

0

A dlaczego nie użyjesz boost::thread?
Proste przyjemne, wieloplatformowe tylko dokumentacja do du..

1 użytkowników online, w tym zalogowanych: 0, gości: 1