5#include "../Foundation/Compiler.h"
6#ifndef SC_EXPORT_LIBRARY_FILE_SYSTEM_WATCHER
7#define SC_EXPORT_LIBRARY_FILE_SYSTEM_WATCHER 0
9#define SC_FILE_SYSTEM_WATCHER_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_FILE_SYSTEM_WATCHER)
11#include "../Foundation/Function.h"
12#include "../Foundation/OpaqueObject.h"
13#include "../Foundation/Result.h"
14#include "../Foundation/StringPath.h"
57 struct InternalDefinition
59 static constexpr int Windows = 3 *
sizeof(
void*);
60 static constexpr int Apple = 42 *
sizeof(
void*);
61 static constexpr int Linux =
sizeof(
void*) * 4;
62 static constexpr int Default = Linux;
64 static constexpr size_t Alignment =
alignof(
void*);
66 using Object = Internal;
78 struct ThreadRunnerInternal;
79 struct ThreadRunnerDefinition
81 static constexpr int MaxWatchablePaths = 1024;
83 static constexpr int Windows = (2 * MaxWatchablePaths + 2) *
sizeof(
void*) +
sizeof(
uint64_t);
84 static constexpr int Apple =
sizeof(
void*);
85 static constexpr int Linux =
sizeof(
void*) * 6;
86 static constexpr int Default = Linux;
88 static constexpr size_t Alignment =
alignof(
void*);
90 using Object = ThreadRunnerInternal;
93 struct FolderWatcherInternal;
94 struct FolderWatcherSizes
96 static constexpr int MaxNumberOfSubdirs = 128;
97 static constexpr int MaxChangesBufferSize = 1024;
99 static constexpr int Windows = MaxChangesBufferSize +
sizeof(
void*) +
sizeof(
void*);
100 static constexpr int Apple =
sizeof(
void*);
101 static constexpr int Linux = 1056 + 4096 + 8;
102 static constexpr int Default = Linux;
104 static constexpr size_t Alignment =
alignof(
void*);
106 using Object = FolderWatcherInternal;
131 friend struct Internal;
159 template <
typename T_AsyncEventLoop>
161#if SC_PLATFORM_WINDOWS
162#if SC_ASYNC_ENABLE_LOG
188 virtual Result appleStartWakeUp() = 0;
189 virtual void appleSignalEventObject() = 0;
190 virtual Result appleWakeUpAndWait() = 0;
192#elif SC_PLATFORM_LINUX
193 virtual Result linuxStartSharedFilePoll() = 0;
194 virtual Result linuxStopSharedFilePoll() = 0;
201 virtual void* windowsGetOverlapped(
FolderWatcher& watcher) = 0;
203 friend struct Internal;
236 friend decltype(internal);
237 friend decltype(FolderWatcher::internal);
238 template <
typename T_AsyncEventLoop>
241 struct WatcherLinkedList
249 WatcherLinkedList watchers;
258template <
typename T_AsyncEventLoop>
263 using T_AsyncLoopWakeUp =
typename T_AsyncEventLoop::LoopWakeUp;
264 using T_AsyncFilePoll =
typename T_AsyncEventLoop::FilePoll;
265 using T_EventObject =
typename T_AsyncEventLoop::EventObjectType;
266 using T_AsyncResult =
typename T_AsyncEventLoop::ResultType;
268 void init(T_AsyncEventLoop& loop) { eventLoop = &loop; }
271 T_AsyncEventLoop* eventLoop =
nullptr;
274 virtual Result appleStartWakeUp()
override
276 SC_TRY_MSG(eventLoop !=
nullptr and fileSystemWatcher !=
nullptr,
"FileSystemWatcherAsync not initialized");
277 T_AsyncLoopWakeUp& wakeUp = asyncWakeUp;
278 wakeUp.callback.template bind<Self, &Self::onEventLoopNotification>(*
this);
279 return wakeUp.start(*eventLoop, eventObject);
282 virtual void appleSignalEventObject()
override { eventObject.signal(); }
284 virtual Result appleWakeUpAndWait()
override
286 const Result res = asyncWakeUp.wakeUp(*eventLoop);
291 void onEventLoopNotification(
typename T_AsyncLoopWakeUp::Result& result)
293 fileSystemWatcher->asyncNotify(
nullptr);
294 result.reactivateRequest(
true);
297 T_AsyncLoopWakeUp asyncWakeUp = {};
298 T_EventObject eventObject = {};
299#elif SC_PLATFORM_LINUX
300 virtual Result linuxStartSharedFilePoll()
override
302 SC_TRY_MSG(eventLoop !=
nullptr and fileSystemWatcher !=
nullptr,
"FileSystemWatcherAsync not initialized");
303 SC_TRY(eventLoop->associateExternallyCreatedFileDescriptorHandle(notifyFd));
304 asyncPoll.callback.template bind<Self, &Self::onEventLoopNotification>(*
this);
305 return asyncPoll.start(*eventLoop, notifyFd);
308 virtual Result linuxStopSharedFilePoll()
override {
return asyncPoll.stop(*eventLoop); }
310 void onEventLoopNotification(
typename T_AsyncFilePoll::Result& result)
312 fileSystemWatcher->asyncNotify(
nullptr);
313 result.reactivateRequest(
true);
316 T_AsyncFilePoll asyncPoll = {};
321 SC_TRY_MSG(eventLoop !=
nullptr and fileSystemWatcher !=
nullptr,
"FileSystemWatcherAsync not initialized");
322 SC_TRY(eventLoop->associateExternallyCreatedFileDescriptorHandle(handle));
323 T_AsyncFilePoll& asyncPoll = watcher.asyncStorage.template reinterpret_as<T_AsyncFilePoll>();
324 placementNew(asyncPoll);
325 asyncPoll.setDebugName(
"FileSystemWatcherAsync Poll");
326 asyncPoll.callback.template bind<Self, &Self::onEventLoopNotification>(*
this);
327 return asyncPoll.start(*eventLoop, handle);
334 T_AsyncFilePoll& asyncPoll = watcher.asyncStorage.template reinterpret_as<T_AsyncFilePoll>();
336 onAsyncPollClose = [&watcher](T_AsyncResult&)
338 T_AsyncFilePoll& asyncPoll = watcher.asyncStorage.template reinterpret_as<T_AsyncFilePoll>();
339 asyncPoll.~T_AsyncFilePoll();
341 return asyncPoll.stop(*eventLoop, &onAsyncPollClose);
344 virtual void* windowsGetOverlapped(
FolderWatcher& watcher)
override
346 T_AsyncFilePoll& asyncPoll = watcher.asyncStorage.template reinterpret_as<T_AsyncFilePoll>();
347 return asyncPoll.getOverlappedPtr();
350 void onEventLoopNotification(
typename T_AsyncFilePoll::Result& result)
353 auto& storage =
reinterpret_cast<decltype(FolderWatcher::asyncStorage)&
>(result.getAsync());
355 fileSystemWatcher->asyncNotify(&watcher);
356 result.reactivateRequest(
true);
360 Function<void(T_AsyncResult&)> onAsyncPollClose;
#define SC_COMPILER_WARNING_POP
Pops warning from inside a macro.
Definition Compiler.h:120
#define SC_COMPILER_WARNING_PUSH_OFFSETOF
Disables invalid-offsetof gcc and clang warning.
Definition Compiler.h:140
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
#define SC_TRY_MSG(expression, failedMessage)
Checks the value of the given expression and if failed, returns a result with failedMessage to caller...
Definition Result.h:60
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition Result.h:49
A buffer of bytes with given alignment.
Definition AlignedStorage.h:29
FileSystemWatcherAsyncT is an implementation of SC::FileSystemWatcher that uses SC::Async.
Definition FileSystemWatcher.h:260
Abstract class to use event loop notifications (see SC::FileSystemWatcherAsync).
Definition FileSystemWatcher.h:183
Represents a single folder being watched.
Definition FileSystemWatcher.h:141
Function< void(const Notification &)> notifyCallback
Function that will be called on a notification.
Definition FileSystemWatcher.h:148
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:120
StringSpan relativePath
Relative path of the file being notified from basePath
Definition FileSystemWatcher.h:122
Operation operation
Notification type.
Definition FileSystemWatcher.h:123
StringSpan basePath
Reference to the watched directory.
Definition FileSystemWatcher.h:121
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:53
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:113
@ 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.
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
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:42
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37