Назад к задачам
Junior — Senior
9

Оптимизация многопоточного менеджера файловых путей

Компании, где спрашивали:

ГК Адепт
Получайте помощь с лайвкодингом в реальном времени с Sobes Copilot
Условие задачи

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

Сценарий использования:

  • Один поток создает файлы на сервере и передаёт их пути в объект класса.
  • Другой поток генерирует временные файлы локально и тоже передаёт пути.
  • Несколько дополнительных потоков извлекают из класса нужные пути (все файлы, только временные и резервные, только обычные).

Задача – провести рефакторинг и оптимизацию класса, обеспечив корректную работу в многопоточной среде.

# include <vector>
# include <string>
# include <mutex>

using namespace std;

class temporaryGeneratedFilesObserver {
public:
    temporaryGeneratedFilesObserver(vector<string> f) {
        AddFiles(f);
    }

    void AddFiles(vector<string> f) noexcept {
        size_t i = f.size();
        try {
            m_mutex.lock();
            for (i = 0; i < f.size(); i++) {
                m_files.push_back(f[i]);
            }
            m_mutex.unlock();
        } catch (...) {
            m_files.erase(m_files.end() - i, m_files.end());
        }
    }

    vector<string> GetTempBackupFiles() {
        return GetFilesImpl(Backup | Temp);
    }

    vector<string> GetRegularFiles() {
        return GetFilesImpl(Regular);
    }

    vector<string> GetAllFiles() {
        return GetFilesImpl(All);
    }

private:
    enum Flags {
        Temp = 1,
        Backup = 2,
        Regular = 4,
        All = 7
    };

    vector<string> GetFilesImpl(uint32_t flags) {
        m_mutex.lock();

        vector<string> v = m_files;
        for (size_t i = 0; i < v.size(); i++) {
            if ((flags & Temp) && v[i].substr(v[i].size() - 4) == ".tmp") {
                v.erase(v.begin() + i--);
            }
            if ((flags & Backup) && v[i].substr(v[i].size() - 4) == ".bak") {
                v.erase(v.begin() + i--);
            }
            if ((flags & Regular) &&
                v[i].substr(v[i].size() - 4) != ".bak" &&
                v[i].substr(v[i].size() - 4) != ".tmp") {
                v.erase(v.begin() + i--);
            }
        }

        m_mutex.unlock();
        return v;
    }

    mutex m_mutex;
    vector<string> m_files;
};