Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
FileSystemWatcher.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "../Foundation/Function.h"
6#include "../Foundation/OpaqueObject.h"
7#include "../Foundation/Result.h"
8#include "../Foundation/StringPath.h"
9#include "../Threading/Threading.h" // sizeof(Mutex)
10
11namespace SC
12{
13
16
19
39
42{
43 private:
44 struct Internal;
45
46 struct InternalDefinition
47 {
48 static constexpr int Windows = 3 * sizeof(void*);
49 static constexpr int Apple = 43 * sizeof(void*) + sizeof(Mutex);
50 static constexpr int Linux = sizeof(void*) * 4;
51 static constexpr int Default = Linux;
52
53 static constexpr size_t Alignment = alignof(void*);
54
55 using Object = Internal;
56 };
57
58 public:
59 // Must be public to avoid GCC complaining
61
62 private:
63 InternalOpaque internal;
64
65 //...
67 struct ThreadRunnerInternal;
68 struct ThreadRunnerDefinition
69 {
70 static constexpr int MaxWatchablePaths = 1024;
71 static constexpr int Windows =
72 (2 * MaxWatchablePaths) * sizeof(void*) + sizeof(uint64_t) + sizeof(Thread) + sizeof(Action);
73 static constexpr int Apple = sizeof(void*);
74 static constexpr int Linux = sizeof(Thread) + sizeof(void*) * 2;
75 static constexpr int Default = Linux;
76
77 static constexpr size_t Alignment = alignof(void*);
78
79 using Object = ThreadRunnerInternal;
80 };
81
82 struct FolderWatcherInternal;
83 struct FolderWatcherSizes
84 {
85 static constexpr int MaxNumberOfSubdirs = 128; // Max number of subfolders tracked in a watcher
86 static constexpr int MaxChangesBufferSize = 1024;
87 static constexpr int Windows = MaxChangesBufferSize + sizeof(void*) + sizeof(void*);
88 static constexpr int Apple = sizeof(void*);
89 static constexpr int Linux = 1056 + 1024 + 8;
90 static constexpr int Default = Linux;
91
92 static constexpr size_t Alignment = alignof(void*);
93
94 using Object = FolderWatcherInternal;
95 };
96
97 public:
100 enum class Operation
101 {
102 Modified,
104 };
105
108 {
112
117
118 private:
119 friend struct Internal;
120#if SC_PLATFORM_APPLE
121 StringSpan fullPath;
122#endif
123 };
124
129 {
134 FolderWatcher(Span<char> subFolderRelativePathsBuffer = {});
135
137
141
143 void setDebugName(const char* debugName);
144
145 private:
146 friend struct FileSystemWatcher;
147 friend struct FileSystemWatcherAsync;
148#if SC_PLATFORM_WINDOWS
149 AlignedStorage<112> asyncStorage;
150#endif
152
153 FileSystemWatcher* parent = nullptr;
154 FolderWatcher* next = nullptr;
155 FolderWatcher* prev = nullptr;
156
157 StringPath path;
158
159#if SC_PLATFORM_LINUX
160 Span<char> subFolderRelativePathsBuffer;
161#endif
162 };
163
166 {
167 virtual ~EventLoopRunner() {}
168
169 protected:
170#if SC_PLATFORM_APPLE
171 virtual Result appleStartWakeUp() = 0;
172 virtual void appleSignalEventObject() = 0;
173 virtual Result appleWakeUpAndWait() = 0;
174
175#elif SC_PLATFORM_LINUX
176 virtual Result linuxStartSharedFilePoll() = 0;
177 virtual Result linuxStopSharedFilePoll() = 0;
178
179 int notifyFd = -1;
180
181#else
182 virtual Result windowsStartFolderFilePoll(FolderWatcher& watcher, void* handle) = 0;
183 virtual Result windowsStopFolderFilePoll(FolderWatcher& watcher) = 0;
184 virtual void* windowsGetOverlapped(FolderWatcher& watcher) = 0;
185#endif
186 friend struct Internal;
187 FileSystemWatcher* fileSystemWatcher = nullptr;
188
189 void internalInit(FileSystemWatcher& fsWatcher, int handle);
190 };
191
194
199
204
208
215
216 void asyncNotify(FolderWatcher* watcher);
217
218 private:
219 friend decltype(internal);
220 friend decltype(FolderWatcher::internal);
221 friend struct EventLoopRunner;
222 // Trimmed duplicate of IntrusiveDoubleLinkedList<T>
223 struct WatcherLinkedList
224 {
225 FolderWatcher* back = nullptr; // has no next
226 FolderWatcher* front = nullptr; // has no prev
227
228 [[nodiscard]] bool isEmpty() const { return front == nullptr; }
229
230 void queueBack(FolderWatcher& watcher);
231 void remove(FolderWatcher& watcher);
232 };
233 WatcherLinkedList watchers;
234};
235
237} // namespace SC
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:42
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
FileSystemWatcherAsync is an implementation of SC::FileSystemWatcher that uses SC::Async.
Definition FileSystemWatcherAsync.h:30
Abstract class to use event loop notifications (see SC::FileSystemWatcherAsync).
Definition FileSystemWatcher.h:166
Represents a single folder being watched.
Definition FileSystemWatcher.h:129
Function< void(const Notification &)> notifyCallback
Function that will be called on a notification.
Definition FileSystemWatcher.h:136
FolderWatcher(Span< char > subFolderRelativePathsBuffer={})
Constructs a folder watcher.
void setDebugName(const char *debugName)
Sets debug name for AsyncFilePoll used on Windows (used only for debug purposes)
Result stopWatching()
Stop watching this directory.
Notification holding type and path.
Definition FileSystemWatcher.h:108
StringSpan relativePath
Relative path of the file being notified from basePath
Definition FileSystemWatcher.h:110
Operation operation
Notification type.
Definition FileSystemWatcher.h:111
StringSpan basePath
Reference to the watched directory.
Definition FileSystemWatcher.h:109
SC::Result getFullPath(StringPath &path) const
Get the full path of the file being watched.
Notifies about events (add, remove, rename, modified) on files and directories.
Definition FileSystemWatcher.h:42
Result close()
Stops all watchers and frees the ThreadRunner or EventLoopRunner passed in init.
Result init(EventLoopRunner &runner)
Setup watcher to receive async notifications on an event loop.
Result init(ThreadRunner &runner)
Setup watcher to receive notifications from a background thread.
Operation
Specifies the event classes.
Definition FileSystemWatcher.h:101
@ Modified
A file or directory has been modified in its contents and/or timestamp.
@ AddRemoveRename
A file or directory has been added, removed or renamed.
Result watch(FolderWatcher &watcher, StringSpan path)
Starts watching a single directory, calling FolderWatcher::notifyCallback on file events.
A native OS mutex to synchronize access to shared resources.
Definition Threading.h:28
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:12
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
Pre-sized char array holding enough space to represent a file system path.
Definition StringPath.h:41
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
A native OS thread.
Definition Threading.h:118