Sane C++ Libraries
C++ Platform Abstraction Libraries
SC::FileSystemWatcher Struct Reference

Notifies about events (add, remove, rename, modified) on files and directories. More...

#include <FileSystemWatcher.h>

Classes

struct  EventLoopRunner
 Delivers notifications using Async (SC::AsyncEventLoop). More...
 
struct  FolderWatcher
 Represents a single folder being watched. More...
 
struct  Notification
 Notification holding type and path. More...
 

Public Types

enum class  Operation {
  Modified ,
  AddRemoveRename
}
 Specifies the event classes. More...
 
using ThreadRunner = OpaqueObject< ThreadRunnerDefinition >
 Delivers notifications on a background thread. More...
 

Public Member Functions

Result init (ThreadRunner &runner)
 Setup watcher to receive notifications from a background thread. More...
 
Result init (EventLoopRunner &runner, AsyncEventLoop &eventLoop)
 Setup watcher to receive async notifications on SC::AsyncEventLoop. More...
 
Result close ()
 Stops all watchers and frees the ThreadRunner or EventLoopRunner passed in init. More...
 
Result watch (FolderWatcher &watcher, StringView path)
 Starts watching a single directory, calling FolderWatcher::notifyCallback on file events. More...
 

Friends

decltype(internal) friend decltype(FolderWatcher::internal) IntrusiveDoubleLinkedList< FolderWatcherwatchers
 

Detailed Description

Notifies about events (add, remove, rename, modified) on files and directories.

Caller can specify a callback for receiving notifications the SC::FileSystemWatcher::watch method.

Changes are grouped in two categories:

  • Added, removed and renamed files and directories
  • Modified files

There are two modes in which FileSystemWatcher can be initialized, defining how notifications are delivered:

Mode Description
SC::FileSystemWatcher::ThreadRunner Delivers notifications on a background thread.
SC::FileSystemWatcher::EventLoopRunner Delivers notifications using Async (SC::AsyncEventLoop).

Example using SC::FileSystemWatcher::EventLoopRunner:

// Initialize the FileSystemWatcher
FileSystemWatcher fileSystemWatcher;
FileSystemWatcher::EventLoopRunner eventLoopRunner;
SC_TRY(fileSystemWatcher.init(eventLoopRunner, eventLoop));
// Setup notification callback
auto onFileModified = [&](const FileSystemWatcher::Notification& notification)
{
// This callback will be called from the thread calling AsyncEventLoop::run
SmallString<1024> buffer;
StringView fullPath;
if (notification.getFullPath(buffer, fullPath))
{
switch (notification.operation)
{
case FileSystemWatcher::Operation::Modified: // File has been modified
console.print("Modified {} {}\n", notification.relativePath, fullPath);
break;
case FileSystemWatcher::Operation::AddRemoveRename: // File was added / removed
console.print("AddRemoveRename {} {}\n", notification.relativePath, fullPath);
break;
}
}
};
// Start watching a specific folder
FileSystemWatcher::FolderWatcher folderWatcher;
folderWatcher.notifyCallback = onFileModified;
SC_TRY(fileSystemWatcher.watch(folderWatcher, "/path/to/dir"));
// ...
// At a later point when there is no more need of watching the folder
SC_TRY(folderWatcher.stopWatching());
// ...
// When all watchers have been unwatched and to dispose all system resources
SC_TRY(fileSystemWatcher.close());
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition: Result.h:47
@ 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.

Example using SC::FileSystemWatcher::ThreadRunner:

// Initialize the FileSystemWatcher
FileSystemWatcher::ThreadRunner threadRunner; // <--- The thread runner
FileSystemWatcher fileSystemWatcher;
SC_TRY(fileSystemWatcher.init(threadRunner));
// Setup notification callback
auto onFileModified = [&](const FileSystemWatcher::Notification& notification)
{
// Warning! This callback is called from a background thread!
// Make sure to do proper synchronization!
SmallString<1024> buffer;
StringView fullPath;
if (notification.getFullPath(buffer, fullPath))
{
switch (notification.operation)
{
case FileSystemWatcher::Operation::Modified: // File has been modified
console.print("Modified {} {}\n", notification.relativePath, fullPath);
break;
case FileSystemWatcher::Operation::AddRemoveRename: // File was added / removed
console.print("AddRemoveRename {} {}\n", notification.relativePath, fullPath);
break;
}
}
};
// Start watching a specific folder
FileSystemWatcher::FolderWatcher folderWatcher;
folderWatcher.notifyCallback = onFileModified;
SC_TRY(fileSystemWatcher.watch(folderWatcher, "/path/to/dir"));
// ...
// At a later point when there is no more need of watching the folder
SC_TRY(folderWatcher.stopWatching());
// ...
// When all watchers have been unwatched and to dispose all system resources
SC_TRY(fileSystemWatcher.close());
OpaqueObject< ThreadRunnerDefinition > ThreadRunner
Delivers notifications on a background thread.
Definition: FileSystemWatcher.h:159

Member Typedef Documentation

◆ ThreadRunner

using SC::FileSystemWatcher::ThreadRunner = OpaqueObject<ThreadRunnerDefinition>

Delivers notifications on a background thread.

Member Enumeration Documentation

◆ Operation

Specifies the event classes.

Some events are grouped in a single one because it's non-trivial providing precise notifications that are consistent across platforms.

Enumerator
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.

Member Function Documentation

◆ close()

Result SC::FileSystemWatcher::close ( )

Stops all watchers and frees the ThreadRunner or EventLoopRunner passed in init.

Returns
Valid Result if resources have been freed successfully

◆ init() [1/2]

Result SC::FileSystemWatcher::init ( EventLoopRunner runner,
AsyncEventLoop eventLoop 
)

Setup watcher to receive async notifications on SC::AsyncEventLoop.

Parameters
runnerAddress of a ThreadRunner object that must be valid until close()
eventLoopA valid AsyncEventLoop
Returns
Valid Result if the watcher has been initialized correctly

◆ init() [2/2]

Result SC::FileSystemWatcher::init ( ThreadRunner runner)

Setup watcher to receive notifications from a background thread.

Parameters
runnerAddress of a ThreadRunner object that must be valid until close()
Returns
Valid Result if the watcher has been initialized correctly

◆ watch()

Result SC::FileSystemWatcher::watch ( FolderWatcher watcher,
StringView  path 
)

Starts watching a single directory, calling FolderWatcher::notifyCallback on file events.

Parameters
watcherReference to a (not already used) watcher, with a valid FolderWatcher::notifyCallback. Its address must not change until FolderWatcher::stopWatching or FileSystemWatcher::close
pathThe directory being monitored
Returns
Valid Result if directory is accessible and the watcher is initialized properly.

The documentation for this struct was generated from the following file: