-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDirectoryWatcher.cpp
108 lines (90 loc) · 3.53 KB
/
DirectoryWatcher.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "DirectoryWatcher.h"
#include <Windows.h>
#include <iostream>
#include <array>
FDirectoryWatcher::FDirectoryWatcher(const std::filesystem::path& InDirToWatch)
: DirToWatch{ std::filesystem::absolute(InDirToWatch) }
{
DirHandle = CreateFile(DirToWatch.string().c_str(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
WorkerThread = std::thread([&]
{
std::vector<UCHAR> Buffer(64 * 1024, 0);
DWORD BytesReturned;
while (bShouldWatch)
{
bIsWaiting = true;
constexpr DWORD NotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE;
if (ReadDirectoryChangesW(DirHandle, Buffer.data(), static_cast<DWORD>(Buffer.size() * sizeof(UCHAR)), FALSE, NotifyFilter, &BytesReturned, NULL, NULL) == TRUE)
{
DWORD Offset = 0;
FILE_NOTIFY_INFORMATION* Info;
do
{
Info = (FILE_NOTIFY_INFORMATION*) &Buffer[Offset];
#if 0
switch (Info->Action)
{
case FILE_ACTION_ADDED:
std::cout << "Add: ";
break;
case FILE_ACTION_MODIFIED:
std::cout << "Modified: ";
break;
case FILE_ACTION_REMOVED:
std::cout << "Removed: ";
break;
case FILE_ACTION_RENAMED_NEW_NAME:
std::cout << "Renamed New Name: ";
break;
case FILE_ACTION_RENAMED_OLD_NAME:
std::cout << "Renamed Old Name: ";
break;
}
std::wstring FileNameW{ Info->FileName, Info->FileNameLength / sizeof(WCHAR) };
std::filesystem::path FilePath{ FileNameW };
std::cout << FilePath << std::endl;
#endif
switch (Info->Action)
{
case FILE_ACTION_MODIFIED:
case FILE_ACTION_RENAMED_NEW_NAME:
{
const std::wstring FileNameW{ Info->FileName, Info->FileNameLength / sizeof(WCHAR) };
const std::filesystem::path FilePath{ FileNameW };
{
std::lock_guard Lock{ FilesChangedMutex };
FilesChanged.insert(DirToWatch / FilePath);
}
break;
}
}
Offset += Info->NextEntryOffset;
}
while (Info->NextEntryOffset != 0);
}
bIsWaiting = false;
}
});
}
FDirectoryWatcher::~FDirectoryWatcher()
{
bShouldWatch = false;
while (bIsWaiting)
{
CancelIoEx(DirHandle, NULL);
}
WorkerThread.join();
CloseHandle(DirHandle);
}
std::set<std::filesystem::path> FDirectoryWatcher::GetChangedFiles()
{
std::lock_guard Lock{ FilesChangedMutex };
std::set<std::filesystem::path> ChangedFiles = FilesChanged;
FilesChanged.clear();
return ChangedFiles;
}