Commit 60955feab8
Changed files (3)
src-self-hosted
src-self-hosted/compilation.zig
@@ -758,32 +758,28 @@ pub const Compilation = struct {
// First, get an item from the watch channel, waiting on the channel.
var group = event.Group(BuildError!void).init(self.loop);
{
- const ev = await (async self.fs_watch.channel.get() catch unreachable);
- const root_scope = switch (ev) {
- fs.Watch(*Scope.Root).Event.CloseWrite => |x| x,
- fs.Watch(*Scope.Root).Event.Err => |err| {
- build_result = err;
- continue;
- },
+ const ev = (await (async self.fs_watch.channel.get() catch unreachable)) catch |err| {
+ build_result = err;
+ continue;
};
+ const root_scope = ev.data;
group.call(rebuildFile, self, root_scope) catch |err| {
build_result = err;
continue;
};
}
// Next, get all the items from the channel that are buffered up.
- while (await (async self.fs_watch.channel.getOrNull() catch unreachable)) |ev| {
- const root_scope = switch (ev) {
- fs.Watch(*Scope.Root).Event.CloseWrite => |x| x,
- fs.Watch(*Scope.Root).Event.Err => |err| {
+ while (await (async self.fs_watch.channel.getOrNull() catch unreachable)) |ev_or_err| {
+ if (ev_or_err) |ev| {
+ const root_scope = ev.data;
+ group.call(rebuildFile, self, root_scope) catch |err| {
build_result = err;
continue;
- },
- };
- group.call(rebuildFile, self, root_scope) catch |err| {
+ };
+ } else |err| {
build_result = err;
continue;
- };
+ }
}
build_result = await (async group.wait() catch unreachable);
}
std/event/fs.zig
@@ -358,9 +358,20 @@ pub async fn readFile(loop: *event.Loop, file_path: []const u8, max_size: usize)
}
}
+pub const WatchEventId = enum {
+ CloseWrite,
+ Delete,
+};
+
+pub const WatchEventError = error{
+ UserResourceLimitReached,
+ SystemResources,
+ AccessDenied,
+};
+
pub fn Watch(comptime V: type) type {
return struct {
- channel: *event.Channel(Event),
+ channel: *event.Channel(Event.Error!Event),
os_data: OsData,
const OsData = switch (builtin.os) {
@@ -395,19 +406,16 @@ pub fn Watch(comptime V: type) type {
file_table: OsData.FileTable,
};
- pub const Event = union(enum) {
- CloseWrite: V,
- Err: Error,
+ pub const Event = struct {
+ id: Id,
+ data: V,
- pub const Error = error{
- UserResourceLimitReached,
- SystemResources,
- AccessDenied,
- };
+ pub const Id = WatchEventId;
+ pub const Error = WatchEventError;
};
pub fn create(loop: *event.Loop, event_buf_count: usize) !*Self {
- const channel = try event.Channel(Self.Event).create(loop, event_buf_count);
+ const channel = try event.Channel(Self.Event.Error!Self.Event).create(loop, event_buf_count);
errdefer channel.destroy();
switch (builtin.os) {
@@ -519,19 +527,32 @@ pub fn Watch(comptime V: type) type {
}
while (true) {
- (await (async self.channel.loop.bsdWaitKev(
- @intCast(usize, close_op.getHandle()), posix.EVFILT_VNODE, posix.NOTE_WRITE,
- ) catch unreachable)) catch |err| switch (err) {
+ if (await (async self.channel.loop.bsdWaitKev(
+ @intCast(usize, close_op.getHandle()),
+ posix.EVFILT_VNODE,
+ posix.NOTE_WRITE | posix.NOTE_DELETE,
+ ) catch unreachable)) |kev| {
+ // TODO handle EV_ERROR
+ if (kev.fflags & posix.NOTE_DELETE != 0) {
+ await (async self.channel.put(Self.Event{
+ .id = Event.Id.Delete,
+ .data = value_copy,
+ }) catch unreachable);
+ } else if (kev.fflags & posix.NOTE_WRITE != 0) {
+ await (async self.channel.put(Self.Event{
+ .id = Event.Id.CloseWrite,
+ .data = value_copy,
+ }) catch unreachable);
+ }
+ } else |err| switch (err) {
error.EventNotFound => unreachable,
error.ProcessNotFound => unreachable,
error.AccessDenied, error.SystemResources => {
// TODO https://github.com/ziglang/zig/issues/769
const casted_err = @errSetCast(error{AccessDenied,SystemResources}, err);
- await (async self.channel.put(Self.Event{ .Err = casted_err }) catch unreachable);
+ await (async self.channel.put(casted_err) catch unreachable);
},
- };
-
- await (async self.channel.put(Self.Event{ .CloseWrite = value_copy }) catch unreachable);
+ }
}
}
@@ -582,7 +603,7 @@ pub fn Watch(comptime V: type) type {
@panic("TODO");
}
- async fn linuxEventPutter(inotify_fd: i32, channel: *event.Channel(Event), out_watch: **Self) void {
+ async fn linuxEventPutter(inotify_fd: i32, channel: *event.Channel(Event.Error!Event), out_watch: **Self) void {
// TODO https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
@@ -743,9 +764,9 @@ async fn testFsWatch(loop: *event.Loop) !void {
}
ev_consumed = true;
- switch (await ev) {
- Watch(void).Event.CloseWrite => {},
- Watch(void).Event.Err => |err| return err,
+ switch ((try await ev).id) {
+ WatchEventId.CloseWrite => {},
+ WatchEventId.Delete => @panic("wrong event"),
}
const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024);
@@ -753,4 +774,6 @@ async fn testFsWatch(loop: *event.Loop) !void {
\\line 1
\\lorem ipsum
));
+
+ // TODO test deleting the file and then re-adding it. we should get events for both
}
std/event/loop.zig
@@ -52,6 +52,20 @@ pub const Loop = struct {
base: ResumeNode,
kevent: posix.Kevent,
};
+
+ pub const Basic = switch (builtin.os) {
+ builtin.Os.macosx => struct {
+ base: ResumeNode,
+ kev: posix.Kevent,
+ },
+ builtin.Os.linux => struct {
+ base: ResumeNode,
+ },
+ builtin.Os.windows => struct {
+ base: ResumeNode,
+ },
+ else => @compileError("unsupported OS"),
+ };
};
/// After initialization, call run().
@@ -379,28 +393,37 @@ pub const Loop = struct {
defer self.linuxRemoveFd(fd);
suspend {
// TODO explicitly put this memory in the coroutine frame #1194
- var resume_node = ResumeNode{
- .id = ResumeNode.Id.Basic,
- .handle = @handle(),
+ var resume_node = ResumeNode.Basic{
+ .base = ResumeNode{
+ .id = ResumeNode.Id.Basic,
+ .handle = @handle(),
+ },
};
- try self.linuxAddFd(fd, &resume_node, flags);
+ try self.linuxAddFd(fd, &resume_node.base, flags);
}
}
- pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !void {
- defer self.bsdRemoveKev(ident, filter);
+ pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !posix.Kevent {
+ // TODO #1194
suspend {
- // TODO explicitly put this memory in the coroutine frame #1194
- var resume_node = ResumeNode{
+ resume @handle();
+ }
+ var resume_node = ResumeNode.Basic{
+ .base = ResumeNode{
.id = ResumeNode.Id.Basic,
.handle = @handle(),
- };
+ },
+ .kev = undefined,
+ };
+ defer self.bsdRemoveKev(ident, filter);
+ suspend {
try self.bsdAddKev(&resume_node, ident, filter, fflags);
}
+ return resume_node.kev;
}
/// resume_node must live longer than the promise that it holds a reference to.
- pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode, ident: usize, filter: i16, fflags: u32) !void {
+ pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void {
self.beginOneEvent();
errdefer self.finishOneEvent();
var kev = posix.Kevent{
@@ -409,7 +432,7 @@ pub const Loop = struct {
.flags = posix.EV_ADD|posix.EV_ENABLE|posix.EV_CLEAR,
.fflags = fflags,
.data = 0,
- .udata = @ptrToInt(resume_node),
+ .udata = @ptrToInt(&resume_node.base),
};
const kevent_array = (*[1]posix.Kevent)(&kev);
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
@@ -632,7 +655,10 @@ pub const Loop = struct {
const handle = resume_node.handle;
const resume_node_id = resume_node.id;
switch (resume_node_id) {
- ResumeNode.Id.Basic => {},
+ ResumeNode.Id.Basic => {
+ const basic_node = @fieldParentPtr(ResumeNode.Basic, "base", resume_node);
+ basic_node.kev = ev;
+ },
ResumeNode.Id.Stop => return,
ResumeNode.Id.EventFd => {
const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);