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#if SC_ASYNC_ENABLE_LOG
150 AlignedStorage<120> asyncStorage;
151#else
152 AlignedStorage<112> asyncStorage;
153#endif
154#endif
156
157 FileSystemWatcher* parent = nullptr;
158 FolderWatcher* next = nullptr;
159 FolderWatcher* prev = nullptr;
160
161 StringPath path;
162
163#if SC_PLATFORM_LINUX
164 Span<char> subFolderRelativePathsBuffer;
165#endif
166 };
167
170 {
171 virtual ~EventLoopRunner() {}
172
173 protected:
174#if SC_PLATFORM_APPLE
175 virtual Result appleStartWakeUp() = 0;
176 virtual void appleSignalEventObject() = 0;
177 virtual Result appleWakeUpAndWait() = 0;
178
179#elif SC_PLATFORM_LINUX
180 virtual Result linuxStartSharedFilePoll() = 0;
181 virtual Result linuxStopSharedFilePoll() = 0;
182
183 int notifyFd = -1;
184
185#else
186 virtual Result windowsStartFolderFilePoll(FolderWatcher& watcher, void* handle) = 0;
187 virtual Result windowsStopFolderFilePoll(FolderWatcher& watcher) = 0;
188 virtual void* windowsGetOverlapped(FolderWatcher& watcher) = 0;
189#endif
190 friend struct Internal;
191 FileSystemWatcher* fileSystemWatcher = nullptr;
192
193 void internalInit(FileSystemWatcher& fsWatcher, int handle);
194 };
195
198
203
208
212
219
220 void asyncNotify(FolderWatcher* watcher);
221
222 private:
223 friend decltype(internal);
224 friend decltype(FolderWatcher::internal);
225 friend struct EventLoopRunner;
226 // Trimmed duplicate of IntrusiveDoubleLinkedList<T>
227 struct WatcherLinkedList
228 {
229 FolderWatcher* back = nullptr; // has no next
230 FolderWatcher* front = nullptr; // has no prev
231
232 [[nodiscard]] bool isEmpty() const { return front == nullptr; }
233
234 void queueBack(FolderWatcher& watcher);
235 void remove(FolderWatcher& watcher);
236 };
237 WatcherLinkedList watchers;
238};
239
241} // 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:170
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