Skip to content

Commit

Permalink
FileWatcher: Async stat method
Browse files Browse the repository at this point in the history
When using stat() for watching a file and poser's threadpool is running,
do the stat() call on a worker thread to prevent stalling the main
thread on possible I/O issues.
  • Loading branch information
Zirias committed Oct 8, 2024
1 parent 63d82ed commit 8ba637c
Showing 1 changed file with 55 additions and 6 deletions.
61 changes: 55 additions & 6 deletions src/bin/xmoji/filewatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,20 @@
#define WATCHING_EVENTS 2
#define WATCHING_EVDIR 3

typedef struct StatJobData
{
const char *path;
struct timespec modified;
int exists;
} StatJobData;

struct FileWatcher
{
const char *path;
char *dirpath;
PSC_Event *changed;
PSC_ThreadJob *statJob;
StatJobData statJobData;
struct timespec modified;
int exists;
int watching;
Expand All @@ -92,15 +101,31 @@ FileWatcher *FileWatcher_create(const char *path)
return self;
}

static void dostat(void *receiver, void *sender, void *args)
static void dostatjob(void *data)
{
StatJobData *job = data;

struct stat st;
if (stat(job->path, &st) < 0)
{
job->exists = 0;
}
else
{
job->exists = 1;
job->modified = st.st_mtim;
}
}

static void finishstat(void *receiver, void *sender, void *args)
{
(void)sender;
(void)args;

struct stat st;
FileWatcher *self = receiver;
self->statJob = 0;

if (stat(self->path, &st) < 0)
if (!self->statJobData.exists)
{
if (!self->exists) return;
self->exists = 0;
Expand All @@ -111,21 +136,45 @@ static void dostat(void *receiver, void *sender, void *args)

if (!self->exists)
{
self->modified = st.st_mtim;
self->modified = self->statJobData.modified;
self->exists = 1;
FileChange ea = FC_CREATED;
PSC_Event_raise(self->changed, 0, &ea);
return;
}

if (memcmp(&self->modified, &st.st_mtim, sizeof self->modified))
if (memcmp(&self->modified, &self->statJobData.modified,
sizeof self->modified))
{
self->modified = st.st_mtim;
self->modified = self->statJobData.modified;
FileChange ea = FC_MODIFIED;
PSC_Event_raise(self->changed, 0, &ea);
}
}

static void dostat(void *receiver, void *sender, void *args)
{
(void)sender;
(void)args;

FileWatcher *self = receiver;
if (self->statJob) return;
self->statJobData.path = self->path;

if (PSC_ThreadPool_active())
{
self->statJob = PSC_ThreadJob_create(dostatjob, &self->statJobData, 0);
PSC_Event_register(PSC_ThreadJob_finished(self->statJob),
self, finishstat, 0);
PSC_ThreadPool_enqueue(self->statJob);
}
else
{
dostatjob(&self->statJobData);
finishstat(self, 0, 0);
}
}

PSC_Event *FileWatcher_changed(FileWatcher *self)
{
return self->changed;
Expand Down

0 comments on commit 8ba637c

Please sign in to comment.