Skip to content

Commit 29829dd

Browse files
committed
FileSystemWatcher: Remove dependency from Memory library
1 parent 585ee59 commit 29829dd

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

Libraries/FileSystemWatcher/FileSystemWatcher.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
#include "Internal/FileSystemWatcherLinux.inl"
1111
#endif
1212

13+
SC::FileSystemWatcher::FolderWatcher::FolderWatcher(Span<char> buffer)
14+
{
15+
#if SC_PLATFORM_LINUX
16+
subFolderRelativePathsBuffer = buffer;
17+
#else
18+
(void)buffer;
19+
#endif
20+
}
21+
1322
SC::Result SC::FileSystemWatcher::init(EventLoopRunner& runner, AsyncEventLoop& eventLoop)
1423
{
1524
runner.eventLoop = &eventLoop;

Libraries/FileSystemWatcher/FileSystemWatcher.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct FileSystemWatcher
6363
static constexpr int Windows =
6464
MaxChangesBufferSize + sizeof(void*) + sizeof(FileDescriptor) + sizeof(AsyncFilePoll);
6565
static constexpr int Apple = sizeof(void*);
66-
static constexpr int Linux = 1056;
66+
static constexpr int Linux = 1056 + 1024 + 8;
6767
static constexpr int Default = Linux;
6868

6969
static constexpr size_t Alignment = alignof(void*);
@@ -119,6 +119,12 @@ struct FileSystemWatcher
119119
/// @note You can create an SC::ArenaMap to create a buffer of these objects, that can be easily reused.
120120
struct FolderWatcher
121121
{
122+
/// @brief Constructs a folder watcher
123+
/// @param subFolderRelativePathsBuffer User provided buffer used to sub-folders relative paths.
124+
/// When an empty span is passed, the internal 1Kb buffer is used.
125+
/// This buffer is used on Linux only when watching folders recursively, it's unused on Windows / macOS.
126+
FolderWatcher(Span<char> subFolderRelativePathsBuffer = {});
127+
122128
Function<void(const Notification&)> notifyCallback; ///< Function that will be called on a notification
123129

124130
/// @brief Stop watching this directory. After calling it the FolderWatcher can be reused or released.
@@ -138,6 +144,9 @@ struct FileSystemWatcher
138144
StringPath path;
139145

140146
OpaqueObject<FolderWatcherSizes> internal;
147+
#if SC_PLATFORM_LINUX
148+
Span<char> subFolderRelativePathsBuffer;
149+
#endif
141150
};
142151

143152
/// @brief Delivers notifications using @ref library_async (SC::AsyncEventLoop).

Libraries/FileSystemWatcher/Internal/FileSystemWatcherLinux.inl

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// SPDX-License-Identifier: MIT
33
#include "../../FileSystemWatcher/FileSystemWatcher.h"
44

5+
#include "../../Foundation/Assert.h"
56
#include "../../Foundation/Deferred.h"
6-
#include "../../Memory/Buffer.h"
77
#include "../../Threading/Threading.h"
88

99
#include <dirent.h> // opendir, readdir, closedir
@@ -29,9 +29,12 @@ struct SC::FileSystemWatcher::FolderWatcherInternal
2929
Pair notifyHandles[FolderWatcherSizes::MaxNumberOfSubdirs];
3030
size_t notifyHandlesCount = 0;
3131

32-
Buffer relativePaths;
32+
char relativePathsStorage[1024];
33+
StringSpan::NativeWritable relativePaths;
3334

3435
FolderWatcher* parentEntry = nullptr; // We could in theory use SC_COMPILER_FIELD_OFFSET somehow to obtain it...
36+
37+
FolderWatcherInternal() { relativePaths.writableSpan = {relativePathsStorage}; }
3538
};
3639

3740
struct SC::FileSystemWatcher::ThreadRunnerInternal
@@ -116,8 +119,8 @@ struct SC::FileSystemWatcher::Internal
116119
const int res = ::inotify_rm_watch(rootNotifyFd, folderInternal.notifyHandles[idx].notifyID);
117120
SC_TRY_MSG(res != -1, "inotify_rm_watch");
118121
}
119-
folderInternal.notifyHandlesCount = 0; // Reset the count to zero
120-
folderInternal.relativePaths.clear();
122+
folderInternal.notifyHandlesCount = 0; // Reset the count to zero
123+
folderInternal.relativePaths.length = 0;
121124
return Result(true);
122125
}
123126

@@ -128,6 +131,11 @@ struct SC::FileSystemWatcher::Internal
128131
SC_TRY_MSG(entry->path.path.view().getEncoding() != StringEncoding::Utf16,
129132
"FolderWatcher on Linux does not support UTF16 encoded paths. Use UTF8 or ASCII encoding instead.");
130133
FolderWatcherInternal& opaque = entry->internal.get();
134+
if (not entry->subFolderRelativePathsBuffer.empty())
135+
{
136+
opaque.relativePaths.writableSpan = entry->subFolderRelativePathsBuffer;
137+
}
138+
opaque.relativePaths.length = 0;
131139

132140
char currentPath[PATH_MAX];
133141
::memcpy(currentPath, entry->path.path.view().getNullTerminatedNative(), entry->path.path.view().sizeInBytes());
@@ -247,8 +255,10 @@ struct SC::FileSystemWatcher::Internal
247255
relativePath++;
248256
}
249257
pair.notifyID = newHandle;
250-
pair.nameOffset = opaque.relativePaths.size();
251-
SC_TRY(opaque.relativePaths.append({relativePath, ::strlen(relativePath) + 1}));
258+
pair.nameOffset = opaque.relativePaths.length == 0 ? 0 : opaque.relativePaths.length + 1;
259+
StringSpan relativePathSpan = StringSpan::fromNullTerminated(relativePath, StringEncoding::Utf8);
260+
SC_TRY_MSG(relativePathSpan.appendNullTerminatedTo(opaque.relativePaths, false),
261+
"Not enough buffer space to hold sub-folders relative paths");
252262

253263
SC_TRY_MSG(opaque.notifyHandlesCount < FolderWatcherSizes::MaxNumberOfSubdirs,
254264
"Too many subdirectories being watched");
@@ -375,7 +385,9 @@ struct SC::FileSystemWatcher::Internal
375385
{
376386
// Something changed in any of the sub folders of the original root folder being watched
377387
const FolderWatcherInternal& internal = entry->internal.get();
378-
const char* dirStart = internal.relativePaths.data() + internal.notifyHandles[foundIndex].nameOffset;
388+
389+
const char* dirStart =
390+
internal.relativePaths.writableSpan.data() + internal.notifyHandles[foundIndex].nameOffset;
379391

380392
const StringSpan relativeDirectory({dirStart, ::strlen(dirStart)}, true, StringEncoding::Utf8);
381393
const StringSpan relativeName({event->name, event->len - 1}, true, StringEncoding::Utf8);

0 commit comments

Comments
 (0)