Как узнать, закончил ли отдельный std :: thread свое выполнение? - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть функция, подобная следующей, в которой потоки получают блокировку с помощью мьютекса std :: lock_guard и записывают в файл через ofstream.

Когда текущий размер файла увеличивает максимальный размер, я создаюнезависимый поток, который сжимает файл и должен завершиться.

Если файл журнала имеет большой размер (скажем, ~ 500 МБ), сжатие занимает около 25+ секунд.Я отсоединяю поток сжатия, так как никакой другой поток (или основной) не хочет ждать завершения этого потока.

Но мне нужно знать, что поток сжатия не работает до выполнения следующей строки:

_compress_thread(compress_log, _logfile).detach();

Пример кода:

    void log (std::string message)
    {
        // Lock using mutex
        std::lock_guard<std::mutex> lck(mtx);

        _outputFile << message << std::endl;
        _outputFile.flush();
        _sequence_number++;
        _curr_file_size = _outputFile.tellp();

        if (_curr_file_size >= max_size) {
            // Code to close the file stream, rename the file, and reopen
            ...


            // Create an independent thread to compress the file since
            // it takes some time to compress huge files.
            if (the_compress_thread_is_not_already_running) //pseudo code
            {
                _compress_thread(compress_log, _logfile).detach();
            }
        }
    }

В приведенном выше условии if, т.е. the_compress_thread_is_not_already_running, как я могу быть уверен, что поток сжатия не запущен?

void * compress_log (std::string s) 
{

    // Compress the file
    // ...

}

1 Ответ

0 голосов
/ 18 февраля 2019

Невозможно определить, завершился ли отдельный поток выполнения.

Если вам по какой-то причине необходимо гарантировать, что не более одного потока одновременно сжимается, тогда простое решение - использовать std::async.Возвращает объект future .Вы можете запросить будущий объект, завершен ли связанный обратный вызов.Тот же эффект может быть достигнут менее структурированным способом, используя отсоединенный поток, изменяя общую переменную в конце функции (обратите внимание, что общий доступ должен быть синхронизирован).

Другой подход может состоять в том, чтобы постоянно поддерживатькомпрессионная нить, но блокируйте ее, пока не будет выполнено никаких действий.Поток может быть уведомлен с помощью переменной условия, чтобы начать свою работу и после завершения возобновить блокировку до следующего уведомления.

PS Возможно, вы захотите сначала закрыть поток файлов, переименовать файл и снова открыть, удерживая клавишублокировка, чтобы другие потоки могли продолжать входить в новый файл, пока предыдущие журналы - теперь в переименованном файле - сжимаются.

...