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:
commit
4194edb98a
|
@ -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)
|
||||||
|
|
|
@ -50,9 +50,14 @@ void main()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto fil = File(testDir~"/"~testFilename, "wt");
|
File fil;
|
||||||
|
|
||||||
auto tm = eventDriver.timers.create();
|
auto tm = eventDriver.timers.create();
|
||||||
|
eventDriver.timers.set(tm, 500.msecs, 0.msecs);
|
||||||
|
eventDriver.timers.wait(tm, (tm) {
|
||||||
|
try fil = File(testDir~"/"~testFilename, "wt");
|
||||||
|
catch (Exception e) assert(false, e.msg);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -64,6 +69,7 @@ void main()
|
||||||
remove(testDir~"/"~testFilename);
|
remove(testDir~"/"~testFilename);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ExitReason er;
|
ExitReason er;
|
||||||
do er = eventDriver.core.processEvents(Duration.max);
|
do er = eventDriver.core.processEvents(Duration.max);
|
||||||
|
|
Loading…
Reference in a new issue