2016-11-24 38 views
5

Próbuję zaimplementować czasomierza ze standardowym środowisku Oto kod mam:timera zawiesza wątek główny

bool shutdownDetected = false; 

void signal_handler(const int sigid) 
{ 
    shutdownDetected = true; 
} 

int main(int argc, const char * argv[]) 
{ 
    signal(SIGTERM, (sig_t)signal_handler); 

    std::async(std::launch::async, [&]() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

    std::cout << "main function" << std::endl; 

    while (!shutdownDetected) { 
    } 

    return EXIT_SUCCESS; 
} 

W wyniku widzę w wyjście po 5 sekundach:

// 5 seconds left 
On Timer 
main function 

ale chciałbym zobaczyć:

main function 
// 5 seconds left 
On Timer 

Wygląda na to, że moja implementacja również zawiera główny wątek. Jak tego uniknąć?

+1

Nie jestem ekspertem, ale uważam, że to dziwne, że jeszcze jej nie nazywać '.get()' '[na std :: future'] (http://en.cppreference.com/w/cpp/wątek/przyszłość). [który daje zamierzony rezultat, jeśli to robisz.] (http://coliru.stacked-crooked.com/a/f04caae880926851) – Borgleader

+0

Nawet nie trzeba wywoływać 'get', naprawdę. Wystarczy przypisać 'future' do czegoś, aby można było nazwać' get' później – user4581301

+0

@ user4581301 Ohhh, ponieważ tymczasowy zostaje natychmiastowo zniszczony i zawiesza główny wątek zanim zdarzy się cout? – Borgleader

Odpowiedz

3

Twoje polecenie std :: async zwraca std :: future, które jest natychmiast niszczone. Problem polega na tym, że zniszczenie przyszłości wiąże się z "łączeniem" utworzonego wątku, co oznacza, że ​​destruktor będzie czekał, aż wątek się zakończy, a wykonanie kodu w głównym wątku nie przejdzie, dopóki ten proces się nie zakończy.

Prostą odpowiedzią jest przypisanie wyniku twojego std :: async call do zmiennej i prawdopodobnie wywołanie jego funkcji get() w pętli testującej zakończenie.

auto t = std::async(std::launch::async, [&]() { 
    std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
    std::cout << "On TIMER!" << std::endl; 
}); 

std::cout << "main function" << std::endl; 

t.get(); 
3
std::async(std::launch::async, [&]() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

Nie działa chyba przypisać std::future zwrócony przez std::async do zmiennej i przechowywać go dookoła. Nie wiedziałem, dlaczego tak jest, wyraźnie, ponieważ nie mogłem się tym przejmować. Vincent Savard zrobił, a połączone nam dokumentacji na destructor for std::future który mówi:

może blokować jeżeli wszystkie poniższe kryteria są spełnione: wspólne stan został stworzony przez wywołanie std :: async, wspólne państwo jest jeszcze nie gotowy, i to było ostatnie odniesienie do wspólnego państwa.

Ponieważ wycofany std::future nie jest do niczego przypisany, jest natychmiast niszczony i destruktor blokuje do zakończenia.

Zamierzam pominąć procedurę obsługi sygnału, ponieważ nie ma ona wpływu na problem.

#include <iostream> 
#include <future> 

int main() 
{ 
    auto letMeLive = std::async(std::launch::async, []() { 
     std::this_thread::sleep_for(std::chrono::milliseconds{5000}); 
     std::cout << "On TIMER!" << std::endl; 
    }); 

    std::cout << "main function" << std::endl; 

    letMeLive.wait(); // instead of the signal handler 
    return EXIT_SUCCESS; 
}