Merge pull request #111 from vibe-d/polling_watcher_refactor

Separate the polling logic of PollEventDriverWatchers into a separate class
merged-on-behalf-of: Leonid Kramer <l-kramer@users.noreply.github.com>
This commit is contained in:
The Dlang Bot 2019-06-02 09:12:43 +02:00 committed by GitHub
commit 4194edb98a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 46 deletions

View file

@ -332,40 +332,6 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
immutable string m_basePath; immutable string m_basePath;
immutable bool m_recursive; immutable bool m_recursive;
immutable FileChangesCallback m_callback; immutable FileChangesCallback m_callback;
final static class Entry {
Entry parent;
string name;
ulong size;
long lastChange;
this(Entry parent, string name, ulong size, long lastChange)
{
this.parent = parent;
this.name = name;
this.size = size;
this.lastChange = lastChange;
}
string path()
{
import std.path : buildPath;
if (parent)
return buildPath(parent.path, name);
else return name;
}
bool isDir() const { return size == ulong.max; }
}
struct Key {
Entry parent;
string name;
}
// used only within the polling thread
Entry[Key] m_entries;
size_t m_entryCount;
} }
this(shared(Events) event_driver, EventID event, string path, bool recursive, FileChangesCallback callback) this(shared(Events) event_driver, EventID event, string path, bool recursive, FileChangesCallback callback)
@ -378,7 +344,6 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
m_basePath = path; m_basePath = path;
m_recursive = recursive; m_recursive = recursive;
m_callback = callback; m_callback = callback;
scan(false);
try super(&run); try super(&run);
catch (Exception e) assert(false, e.msg); catch (Exception e) assert(false, e.msg);
@ -407,8 +372,16 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
import core.time : MonoTime, msecs; import core.time : MonoTime, msecs;
import std.algorithm.comparison : min; import std.algorithm.comparison : min;
auto poller = new DirectoryPoller(m_basePath, m_recursive, (ch) {
try synchronized (m_changesMutex) {
m_changes ~= ch;
} catch (Exception e) assert(false, "Mutex lock failed: "~e.msg);
});
poller.scan(false);
try while (true) { try while (true) {
auto timeout = MonoTime.currTime() + min(m_entryCount, 60000).msecs + 1000.msecs; auto timeout = MonoTime.currTime() + min(poller.entryCount, 60000).msecs + 1000.msecs;
while (true) { while (true) {
try synchronized (m_changesMutex) { try synchronized (m_changesMutex) {
if (m_changesEvent == EventID.invalid) return; if (m_changesEvent == EventID.invalid) return;
@ -418,7 +391,7 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
sleep(min(1000.msecs, remaining)); sleep(min(1000.msecs, remaining));
} }
scan(true); poller.scan(true);
try synchronized (m_changesMutex) { try synchronized (m_changesMutex) {
if (m_changesEvent == EventID.invalid) return; if (m_changesEvent == EventID.invalid) return;
@ -434,11 +407,62 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
} }
} }
}
private final class DirectoryPoller {
private final static class Entry {
Entry parent;
string name;
ulong size;
long lastChange;
this(Entry parent, string name, ulong size, long lastChange)
{
this.parent = parent;
this.name = name;
this.size = size;
this.lastChange = lastChange;
}
string path()
{
import std.path : buildPath;
if (parent)
return buildPath(parent.path, name);
else return name;
}
bool isDir() const { return size == ulong.max; }
}
private struct Key {
Entry parent;
string name;
}
alias ChangeCallback = void delegate(FileChange) @safe nothrow;
private {
immutable string m_basePath;
immutable bool m_recursive;
Entry[Key] m_entries;
size_t m_entryCount;
ChangeCallback m_onChange;
}
this(string path, bool recursive, ChangeCallback on_change)
{
m_basePath = path;
m_recursive = recursive;
m_onChange = on_change;
}
@property size_t entryCount() const { return m_entryCount; }
private void addChange(FileChangeKind kind, Key key, bool is_dir) private void addChange(FileChangeKind kind, Key key, bool is_dir)
{ {
try synchronized (m_changesMutex) { m_onChange(FileChange(kind, m_basePath, key.parent ? key.parent.path : "", key.name, is_dir));
m_changes ~= FileChange(kind, m_basePath, key.parent ? key.parent.path : "", key.name, is_dir);
} catch (Exception e) assert(false, "Mutex lock failed: "~e.msg);
} }
private void scan(bool generate_changes) private void scan(bool generate_changes)

View file

@ -50,18 +50,24 @@ void main()
} }
}); });
auto fil = File(testDir~"/"~testFilename, "wt"); File fil;
auto tm = eventDriver.timers.create(); auto tm = eventDriver.timers.create();
eventDriver.timers.set(tm, 1500.msecs, 0.msecs); eventDriver.timers.set(tm, 500.msecs, 0.msecs);
eventDriver.timers.wait(tm, (tm) { eventDriver.timers.wait(tm, (tm) {
scope (failure) assert(false); try fil = File(testDir~"/"~testFilename, "wt");
fil.write("test"); catch (Exception e) assert(false, e.msg);
fil.close();
eventDriver.timers.set(tm, 1500.msecs, 0.msecs); eventDriver.timers.set(tm, 1500.msecs, 0.msecs);
eventDriver.timers.wait(tm, (tm) { eventDriver.timers.wait(tm, (tm) {
scope (failure) assert(false); scope (failure) assert(false);
remove(testDir~"/"~testFilename); fil.write("test");
fil.close();
eventDriver.timers.set(tm, 1500.msecs, 0.msecs);
eventDriver.timers.wait(tm, (tm) {
scope (failure) assert(false);
remove(testDir~"/"~testFilename);
});
}); });
}); });