[Common]Use folder_change_reader in file watcher to improve performance (#30827)

This commit is contained in:
Davide Giacometti 2024-01-12 16:23:00 +01:00 коммит произвёл GitHub
Родитель 4ce38d192d
Коммит 4f06f2a659
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 52 добавлений и 45 удалений

Просмотреть файл

@ -1,5 +1,6 @@
#include "pch.h"
#include "FileWatcher.h"
#include <utils/winapi_error.h>
std::optional<FILETIME> FileWatcher::MyFileTime()
{
@ -19,50 +20,47 @@ std::optional<FILETIME> FileWatcher::MyFileTime()
return result;
}
void FileWatcher::Run()
{
while (1)
{
auto lastWrite = MyFileTime();
if (!m_lastWrite.has_value())
{
m_lastWrite = lastWrite;
}
else if (lastWrite.has_value())
{
if (m_lastWrite->dwHighDateTime != lastWrite->dwHighDateTime ||
m_lastWrite->dwLowDateTime != lastWrite->dwLowDateTime)
{
m_lastWrite = lastWrite;
m_callback();
}
}
if (WaitForSingleObject(m_abortEvent, m_refreshPeriod) == WAIT_OBJECT_0)
{
return;
}
}
}
FileWatcher::FileWatcher(const std::wstring& path, std::function<void()> callback, DWORD refreshPeriod) :
m_refreshPeriod(refreshPeriod),
FileWatcher::FileWatcher(const std::wstring& path, std::function<void()> callback) :
m_path(path),
m_callback(callback)
{
m_abortEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (m_abortEvent)
std::filesystem::path fsPath(path);
m_file_name = fsPath.filename();
std::transform(m_file_name.begin(), m_file_name.end(), m_file_name.begin(), ::towlower);
m_folder_change_reader = wil::make_folder_change_reader_nothrow(
fsPath.parent_path().c_str(),
false,
wil::FolderChangeEvents::LastWriteTime,
[this](wil::FolderChangeEvent, PCWSTR fileName) {
std::wstring lowerFileName(fileName);
std::transform(lowerFileName.begin(), lowerFileName.end(), lowerFileName.begin(), ::towlower);
if (m_file_name.compare(fileName) == 0)
{
auto lastWrite = MyFileTime();
if (!m_lastWrite.has_value())
{
m_lastWrite = lastWrite;
}
else if (lastWrite.has_value())
{
if (m_lastWrite->dwHighDateTime != lastWrite->dwHighDateTime ||
m_lastWrite->dwLowDateTime != lastWrite->dwLowDateTime)
{
m_lastWrite = lastWrite;
m_callback();
}
}
}
});
if (!m_folder_change_reader)
{
m_thread = std::thread([this]() { Run(); });
Logger::error(L"Failed to start folder change reader for path {}. {}", path, get_last_error_or_default(GetLastError()));
}
}
FileWatcher::~FileWatcher()
{
if (m_abortEvent)
{
SetEvent(m_abortEvent);
m_thread.join();
CloseHandle(m_abortEvent);
}
m_folder_change_reader.reset();
}

Просмотреть файл

@ -11,16 +11,14 @@
class FileWatcher
{
DWORD m_refreshPeriod;
std::wstring m_path;
std::wstring m_file_name;
std::optional<FILETIME> m_lastWrite;
std::function<void()> m_callback;
HANDLE m_abortEvent;
std::thread m_thread;
wil::unique_folder_change_reader_nothrow m_folder_change_reader;
std::optional<FILETIME> MyFileTime();
void Run();
public:
FileWatcher(const std::wstring& path, std::function<void()> callback, DWORD refreshPeriod = 1000);
FileWatcher(const std::wstring& path, std::function<void()> callback);
~FileWatcher();
};

Просмотреть файл

@ -47,10 +47,15 @@
<ProjectReference Include="..\..\common\version\version.vcxproj">
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
</ProjectReference>
<ProjectReference Include="..\logger\logger.vcxproj">
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@ -58,5 +63,6 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -9,3 +9,5 @@
#include <filesystem>
#include <fstream>
#include <common/logger/logger.h>
#include <wil/filesystem.h>

Просмотреть файл

@ -3,6 +3,7 @@
#include <windows.h>
#include <winrt/base.h>
#include <wil/resource.h>
#include <wil/filesystem.h>
#include <ProjectTelemetry.h>
#include <common/logger/logger.h>

Просмотреть файл

@ -13,8 +13,9 @@
#include <ShellScalingApi.h>
#include <strsafe.h>
#include <TraceLoggingActivity.h>
#include <wil\resource.h>
#include <wil\result.h>
#include <wil/filesystem.h>
#include <wil/resource.h>
#include <wil/result.h>
#include <winrt/windows.foundation.h>
#include <psapi.h>
#include <shared_mutex>

Просмотреть файл

@ -9,6 +9,7 @@
#include <wil/resource.h>
#include <wil/com.h>
#include <wil/filesystem.h>
#include <string_view>
#include <optional>