Многопоточность и синхронизация в C++

418
04 августа 2017, 01:18

Добрый день всем! В ходе работы с многопоточностью в C++ у меня возникли некоторые проблемы. Я качаю некоторые данные(файлы небольшого размера) с некоторого ресурса в многопоточном режиме и сохраняю их все в одну директорию. Когда файлов накапливается в директории очень много(скажем порядка 100000) я хочу создавать новую директорию и перемещать файлы туда. Таким образом у меня получится несколько директорий, каждая из которых содержит по 100000 файлов.

Вот примерный код

#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/bind.hpp>
#include <boost/atomic.hpp>
...
void handler(std::list<std::string> &must_donwloaded, boost::mutex &m, boost::atomic<int> &count_donwloaded)
{
    for (auto it = must_downloaded.begin(); it != must_downloaded.end(); it++
    {
         std::string url_to_file = *it;
         //здесь я делаю запрос к ресурсу и выкачиваю файл
         //после получения файла я его сохраняю в дирректорию
         ....
         //инкрементирую переменную real_downloaded
         real_downloaded++;
    }
}
int main(int argc, char** argv)
{
    boost::mutex m;
    boost::atomic<int> real_downloaded(0);
    //url-ы в списках полностью уникальны. Т.е все они разные
    std::list<std::string> md1 = {"..", "..", "..", ..};
    std::list<std::string> md2 = {"..", "..", ..};
    std::list<std::string> md3 = {"..", "..", "..", "..", ..};
    boost::thread thr1(boost::bind(&handler, boost::ref(md1), boost::ref(m), boost::ref(real_downloaded)));
    boost::thread thr2(boost::bind(&handler, boost::ref(md2), boost::ref(m), boost::ref(real_downloaded)));
    boost::thread thr3(boost::bind(&handler, boost::ref(md3), boost::ref(m), boost::ref(real_downloaded)));
    thr1.join();
    thr2.join();
    thr3.join();
    return 0;

}

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

Подскажите, как мне обойтись здесь и изменить код, чтобы он был потокобезопасным? Нужно не допустить приведенный выше ситуации. Спасибо.

Answer 1

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

READ ALSO
Смысловая нагрузка значения &ldquo;минус NaN&rdquo;

Смысловая нагрузка значения “минус NaN”

В другом вопросе обнаружилось, что деление нуля на переменную, содержащую вещественный ноль, в результате даёт значение -nan

226
Таймаут Write Read

Таймаут Write Read

getlasteror дает ошибку 1008 ругается на hUsb помогите

286
Получение подключенных устройств к Linux на C

Получение подключенных устройств к Linux на C

Задача следующая: необходимо на C/C++ получить список подключенных к ПК на Linux подключенных USB-устройств

269