boost :: filesystem :: recursive_directory_iterator многопоточная безопасность - PullRequest
0 голосов
/ 13 февраля 2020

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

#include <boost/filesystem.hpp>
#include <iostream>

int main()
{
    namespace fs = boost::filesystem;
    size_t size=0;
    if(fs::exists("/home/user/Documents/my_directory") && fs::is_directory("/home/user/Documents/my_directory"))
    {
        try{
            for(auto entry: fs::recursive_directory_iterator("/home/user/Documents/my_directory"))
            {
                if(fs::is_regular_file(entry.status()))
                {
                    size += fs::file_size(entry);
                }
            }
        }
        catch(boost::filesystem::filesystem_error e)
        {
            std::cout << e.code() << std::endl;
            std::cout << e.what() << std::endl;
            std::cout << e.path1() << std::endl;
            std::cout << e.path2() << std::endl;
            return 0;
        }
    }
    std::cout << size << std::endl;
    return 0;
}

Однопоточный он работает нормально, но когда некоторые другие потоки связываются с файлами, я получаю filesystem_error bad descriptor и не могу прочитать любой размер вообще.

Мой вопрос: есть ли какой-нибудь способ сделать какой-то потокобезопасный снимок каталога, чтобы посчитать его размер, или, может быть, другой способ перебрать все файлы, игнорируя отдельные плохие дескрипторы и получить более или менее точный размер?

@ edit: я пытаюсь избежать ошибки: boost :: filesystem :: directory_iterator :: operator ++: неверный дескриптор файла: "/ home / user / Documents / my_directory"

1 Ответ

1 голос
/ 13 февраля 2020

Самое простое решение - просто игнорировать любые ошибки:

#include <boost/filesystem.hpp>
#include <iostream>

int main()
{
    namespace fs = boost::filesystem;
    uintmax_t size=0;
    if(fs::exists("/home/user/Documents/my_directory") && fs::is_directory("/home/user/Documents/my_directory"))
    {
        try{
            for(auto entry: fs::recursive_directory_iterator("/home/user/Documents/my_directory"))
            {
                if(fs::is_regular_file(entry.status()))
                {
                    boost::system::error_code ec;
                    uintmax_t fileSize = fs::file_size(entry, ec);
                    if (!ec)
                    {
                        size += fileSize;
                    }
                }
            }
        }
        catch(boost::filesystem::filesystem_error e)
        {
            std::cout << e.code() << std::endl;
            std::cout << e.what() << std::endl;
            std::cout << e.path1() << std::endl;
            std::cout << e.path2() << std::endl;
            return 0;
        }
    }
    std::cout << size << std::endl;
    return 0;
}

Вы все равно можете получить исключения из recursive_directory_iterator, если каталог удален.

...