该程序的作用是扫描硬盘驱动器中的所有文件。当主线程用所有文件路径填充队列时,多个工作线程开始对文件进行进一步检查。现在我有以下代码:
Scanner.cpp
for (i in words) console.log(words[i])
Scanner.h
#include "Scanner.h"
Scanner::Scanner() : fsscan_done(false)
{
num_threads = thread::hardware_concurrency() - 1;
}
void Scanner::ScanFile(fs::path path)
{
ifstream file(path.c_str());
if (file.is_open())
{
// further inspection
}
}
void Scanner::ThreadScan()
{
while (!fsscan_done || !files.empty()) {
unique_lock<mutex> lock(mtx);
if (files.empty()) {
lock.unlock();
continue;
}
fs::path path = files.front();
files.pop();
lock.unlock();
ScanFile(path);
}
}
void Scanner::Scan()
{
vector<thread> thread_pool;
for (int i = 0; i < num_threads; i++)
thread_pool.push_back(thread(&Scanner::ThreadScan, this));
ScanDirectory("C:\\");
fsscan_done = true;
for (int i = 0; i < num_threads; i++)
thread_pool[i].join();
}
void Scanner::ScanDirectory(fs::path directory)
{
for (const auto & entry : fs::directory_iterator(directory)) {
if (fs::is_directory(entry.path()))
ScanDirectory(entry.path());
else {
if (!fs::is_regular_file(entry.path())) continue;
unique_lock<mutex> lock(mtx);
files.push(entry.path());
}
}
}
我觉得这段代码可以进一步优化,我特别不喜欢这部分:
#pragma once
#include <iostream>
#include <filesystem>
#include <fstream>
#include <mutex>
#include <string>
#include <thread>
#include <queue>
using namespace std;
namespace fs = std::experimental::filesystem;
class Scanner
{
private:
unsigned num_threads;
mutex mtx;
queue<fs::path> files;
bool fsscan_done;
void ThreadScan();
void ScanFile(fs::path file);
public:
Scanner();
void Scan();
void ScanDirectory(fs::path directory);
};
因为我要检查文件为空两次。我认为至少应该有更好的方法来做到这一点。我对多线程原理还很陌生,所以我已经在SO和其他站点上四处看看,也许条件变量可以在这里为我提供帮助,但是我不确定在这种情况下如何实现它们。
编辑:
已将互斥锁的直接锁定和解锁更改为使用unique_lock,谢谢François Andrieux