zig/lib/std/event/loop.zig

1217 lines
46 KiB
Zig
Raw Normal View History

2019-03-02 13:46:04 -08:00
const std = @import("../std.zig");
2018-07-09 19:22:44 -07:00
const builtin = @import("builtin");
const root = @import("root");
2018-07-09 19:22:44 -07:00
const assert = std.debug.assert;
const testing = std.testing;
2018-07-09 19:22:44 -07:00
const mem = std.mem;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
const os = std.os;
const windows = os.windows;
const maxInt = std.math.maxInt;
2019-05-25 10:07:44 -07:00
const Thread = std.Thread;
2018-07-09 19:22:44 -07:00
pub const Loop = struct {
2019-08-08 12:13:05 -07:00
next_tick_queue: std.atomic.Queue(anyframe),
2018-07-09 19:22:44 -07:00
os_data: OsData,
final_resume_node: ResumeNode,
pending_event_count: usize,
2019-05-25 10:07:44 -07:00
extra_threads: []*Thread,
2018-07-09 19:22:44 -07:00
/// For resources that have the same lifetime as the `Loop`.
/// This is only used by `Loop` for the thread pool and associated resources.
arena: std.heap.ArenaAllocator,
/// Pre-allocated eventfds. All permanently active.
/// This is how `Loop` sends promises to be resumed on other threads.
2018-07-09 19:22:44 -07:00
available_eventfd_resume_nodes: std.atomic.Stack(ResumeNode.EventFd),
eventfd_resume_nodes: []std.atomic.Stack(ResumeNode.EventFd).Node,
2019-08-08 12:13:05 -07:00
pub const NextTickNode = std.atomic.Queue(anyframe).Node;
2018-07-09 19:22:44 -07:00
pub const ResumeNode = struct {
2018-07-09 19:22:44 -07:00
id: Id,
2019-08-08 12:13:05 -07:00
handle: anyframe,
overlapped: Overlapped,
2018-09-12 11:26:21 -07:00
pub const overlapped_init = switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.windows => windows.OVERLAPPED{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
.OffsetHigh = 0,
.hEvent = null,
},
else => {},
};
pub const Overlapped = @TypeOf(overlapped_init);
2018-07-09 19:22:44 -07:00
pub const Id = enum {
2018-07-09 19:22:44 -07:00
Basic,
Stop,
EventFd,
};
pub const EventFd = switch (builtin.os) {
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => KEventFd,
2019-05-26 22:35:58 -07:00
.linux => struct {
2018-07-09 19:22:44 -07:00
base: ResumeNode,
epoll_op: u32,
eventfd: i32,
},
2019-05-26 22:35:58 -07:00
.windows => struct {
2018-07-09 19:22:44 -07:00
base: ResumeNode,
completion_key: usize,
},
else => struct {},
2018-07-09 19:22:44 -07:00
};
const KEventFd = struct {
2018-07-09 19:22:44 -07:00
base: ResumeNode,
2019-05-25 10:07:44 -07:00
kevent: os.Kevent,
2018-07-09 19:22:44 -07:00
};
pub const Basic = switch (builtin.os) {
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => KEventBasic,
2019-05-26 22:35:58 -07:00
.linux => struct {
base: ResumeNode,
},
2019-05-26 22:35:58 -07:00
.windows => struct {
base: ResumeNode,
},
else => @compileError("unsupported OS"),
};
2018-08-07 19:23:26 -07:00
const KEventBasic = struct {
2018-08-07 19:23:26 -07:00
base: ResumeNode,
2019-05-25 10:07:44 -07:00
kev: os.Kevent,
2018-08-07 19:23:26 -07:00
};
2018-07-09 19:22:44 -07:00
};
var global_instance_state: Loop = undefined;
const default_instance: ?*Loop = switch (std.io.mode) {
.blocking => null,
.evented => &global_instance_state,
};
pub const instance: ?*Loop = if (@hasDecl(root, "event_loop")) root.event_loop else default_instance;
2019-08-08 13:41:38 -07:00
/// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value.
/// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
pub fn init(self: *Loop) !void {
2019-08-08 13:41:38 -07:00
if (builtin.single_threaded) {
return self.initSingleThreaded();
2019-08-08 13:41:38 -07:00
} else {
return self.initMultiThreaded();
2019-08-08 13:41:38 -07:00
}
}
2018-07-09 19:22:44 -07:00
/// After initialization, call run().
/// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value.
2019-08-08 13:41:38 -07:00
/// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
pub fn initSingleThreaded(self: *Loop) !void {
return self.initThreadPool(1);
2018-07-09 19:22:44 -07:00
}
/// After initialization, call run().
/// This is the same as `initThreadPool` using `Thread.cpuCount` to determine the thread
/// pool size.
2018-07-09 19:22:44 -07:00
/// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value.
2019-08-08 13:41:38 -07:00
/// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
pub fn initMultiThreaded(self: *Loop) !void {
if (builtin.single_threaded)
@compileError("initMultiThreaded unavailable when building in single-threaded mode");
2019-05-26 20:35:26 -07:00
const core_count = try Thread.cpuCount();
return self.initThreadPool(core_count);
2018-07-09 19:22:44 -07:00
}
/// Thread count is the total thread count. The thread pool size will be
/// max(thread_count - 1, 0)
pub fn initThreadPool(self: *Loop, thread_count: usize) !void {
self.* = Loop{
.arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
.pending_event_count = 1,
2018-07-09 19:22:44 -07:00
.os_data = undefined,
2019-08-08 12:13:05 -07:00
.next_tick_queue = std.atomic.Queue(anyframe).init(),
2018-07-09 19:22:44 -07:00
.extra_threads = undefined,
.available_eventfd_resume_nodes = std.atomic.Stack(ResumeNode.EventFd).init(),
.eventfd_resume_nodes = undefined,
.final_resume_node = ResumeNode{
2018-07-09 19:22:44 -07:00
.id = ResumeNode.Id.Stop,
.handle = undefined,
.overlapped = ResumeNode.overlapped_init,
2018-07-09 19:22:44 -07:00
},
};
errdefer self.arena.deinit();
2019-08-17 08:40:48 -07:00
// We need at least one of these in case the fs thread wants to use onNextTick
const extra_thread_count = thread_count - 1;
const resume_node_count = std.math.max(extra_thread_count, 1);
self.eventfd_resume_nodes = try self.arena.allocator.alloc(
2018-07-09 19:22:44 -07:00
std.atomic.Stack(ResumeNode.EventFd).Node,
2019-08-17 08:40:48 -07:00
resume_node_count,
2018-07-09 19:22:44 -07:00
);
self.extra_threads = try self.arena.allocator.alloc(*Thread, extra_thread_count);
2018-07-09 19:22:44 -07:00
try self.initOsData(extra_thread_count);
errdefer self.deinitOsData();
}
pub fn deinit(self: *Loop) void {
self.deinitOsData();
self.arena.deinit();
self.* = undefined;
2018-07-09 19:22:44 -07:00
}
2019-05-26 20:35:26 -07:00
const InitOsDataError = os.EpollCreateError || mem.Allocator.Error || os.EventFdError ||
Thread.SpawnError || os.EpollCtlError || os.KEventError ||
windows.CreateIoCompletionPortError;
2018-07-09 19:22:44 -07:00
const wakeup_bytes = [_]u8{0x1} ** 8;
2018-07-09 19:22:44 -07:00
fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void {
switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.linux => {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
self.os_data.fs_queue = std.atomic.Queue(Request).init();
2019-08-08 13:41:38 -07:00
self.os_data.fs_queue_item = 0;
// we need another thread for the file system because Linux does not have an async
// file system I/O API.
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
self.os_data.fs_end_request = Request.Node{
.data = Request{
.msg = .end,
.finish = .NoAction,
2019-08-08 13:41:38 -07:00
},
};
errdefer {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
2018-07-09 19:22:44 -07:00
}
for (self.eventfd_resume_nodes) |*eventfd_node| {
eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
.data = ResumeNode.EventFd{
.base = ResumeNode{
.id = .EventFd,
2018-07-09 19:22:44 -07:00
.handle = undefined,
.overlapped = ResumeNode.overlapped_init,
2018-07-09 19:22:44 -07:00
},
2019-05-26 20:35:26 -07:00
.eventfd = try os.eventfd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK),
2019-05-25 10:07:44 -07:00
.epoll_op = os.EPOLL_CTL_ADD,
2018-07-09 19:22:44 -07:00
},
.next = undefined,
};
self.available_eventfd_resume_nodes.push(eventfd_node);
}
2019-05-26 20:35:26 -07:00
self.os_data.epollfd = try os.epoll_create1(os.EPOLL_CLOEXEC);
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
errdefer noasync os.close(self.os_data.epollfd);
2018-07-09 19:22:44 -07:00
2019-05-26 20:35:26 -07:00
self.os_data.final_eventfd = try os.eventfd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
errdefer noasync os.close(self.os_data.final_eventfd);
2018-07-09 19:22:44 -07:00
2019-05-25 10:07:44 -07:00
self.os_data.final_eventfd_event = os.epoll_event{
.events = os.EPOLLIN,
.data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },
2018-07-09 19:22:44 -07:00
};
2019-05-26 20:35:26 -07:00
try os.epoll_ctl(
2018-07-09 19:22:44 -07:00
self.os_data.epollfd,
2019-05-25 10:07:44 -07:00
os.EPOLL_CTL_ADD,
2018-07-09 19:22:44 -07:00
self.os_data.final_eventfd,
&self.os_data.final_eventfd_event,
);
2019-08-08 13:41:38 -07:00
self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
errdefer {
2019-08-08 13:41:38 -07:00
self.posixFsRequest(&self.os_data.fs_end_request);
self.os_data.fs_thread.wait();
}
if (builtin.single_threaded) {
assert(extra_thread_count == 0);
return;
}
2018-07-09 19:22:44 -07:00
var extra_thread_index: usize = 0;
errdefer {
// writing 8 bytes to an eventfd cannot fail
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
2018-07-09 19:22:44 -07:00
while (extra_thread_index != 0) {
extra_thread_index -= 1;
self.extra_threads[extra_thread_index].wait();
}
}
while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
2019-05-25 10:07:44 -07:00
self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
2018-07-09 19:22:44 -07:00
}
},
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
2019-05-27 11:12:50 -07:00
self.os_data.kqfd = try os.kqueue();
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
errdefer noasync os.close(self.os_data.kqfd);
2018-07-09 19:22:44 -07:00
2019-05-27 11:12:50 -07:00
self.os_data.fs_kqfd = try os.kqueue();
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
errdefer noasync os.close(self.os_data.fs_kqfd);
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
self.os_data.fs_queue = std.atomic.Queue(Request).init();
// we need another thread for the file system because Darwin does not have an async
// file system I/O API.
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
self.os_data.fs_end_request = Request.Node{
.prev = undefined,
.next = undefined,
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.data = Request{
.msg = .end,
.finish = .NoAction,
},
};
const empty_kevs = &[0]os.Kevent{};
2018-07-09 19:22:44 -07:00
for (self.eventfd_resume_nodes) |*eventfd_node, i| {
eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
.data = ResumeNode.EventFd{
.base = ResumeNode{
2018-07-09 19:22:44 -07:00
.id = ResumeNode.Id.EventFd,
.handle = undefined,
.overlapped = ResumeNode.overlapped_init,
2018-07-09 19:22:44 -07:00
},
// this one is for sending events
2019-05-25 10:07:44 -07:00
.kevent = os.Kevent{
2018-07-09 19:22:44 -07:00
.ident = i,
2019-05-25 10:07:44 -07:00
.filter = os.EVFILT_USER,
.flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE,
2018-07-09 19:22:44 -07:00
.fflags = 0,
.data = 0,
.udata = @ptrToInt(&eventfd_node.data.base),
},
},
.next = undefined,
};
self.available_eventfd_resume_nodes.push(eventfd_node);
const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.data.kevent);
2019-05-27 11:12:50 -07:00
_ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null);
2019-05-25 10:07:44 -07:00
eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE;
eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER;
2018-07-09 19:22:44 -07:00
}
// Pre-add so that we cannot get error.SystemResources
// later when we try to activate it.
2019-05-25 10:07:44 -07:00
self.os_data.final_kevent = os.Kevent{
2018-07-09 19:22:44 -07:00
.ident = extra_thread_count,
2019-05-25 10:07:44 -07:00
.filter = os.EVFILT_USER,
.flags = os.EV_ADD | os.EV_DISABLE,
2018-07-09 19:22:44 -07:00
.fflags = 0,
.data = 0,
.udata = @ptrToInt(&self.final_resume_node),
};
const final_kev_arr = @as(*const [1]os.Kevent, &self.os_data.final_kevent);
2019-05-27 11:12:50 -07:00
_ = try os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);
2019-05-25 10:07:44 -07:00
self.os_data.final_kevent.flags = os.EV_ENABLE;
self.os_data.final_kevent.fflags = os.NOTE_TRIGGER;
2018-07-09 19:22:44 -07:00
2019-05-25 10:07:44 -07:00
self.os_data.fs_kevent_wake = os.Kevent{
2018-08-07 18:06:21 -07:00
.ident = 0,
2019-05-25 10:07:44 -07:00
.filter = os.EVFILT_USER,
.flags = os.EV_ADD | os.EV_ENABLE,
.fflags = os.NOTE_TRIGGER,
.data = 0,
.udata = undefined,
};
2019-05-25 10:07:44 -07:00
self.os_data.fs_kevent_wait = os.Kevent{
2018-08-07 18:06:21 -07:00
.ident = 0,
2019-05-25 10:07:44 -07:00
.filter = os.EVFILT_USER,
.flags = os.EV_ADD | os.EV_CLEAR,
.fflags = 0,
.data = 0,
.udata = undefined,
};
2019-08-08 13:41:38 -07:00
self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
errdefer {
2019-08-08 13:41:38 -07:00
self.posixFsRequest(&self.os_data.fs_end_request);
self.os_data.fs_thread.wait();
}
if (builtin.single_threaded) {
assert(extra_thread_count == 0);
return;
}
2018-07-09 19:22:44 -07:00
var extra_thread_index: usize = 0;
errdefer {
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
2018-07-09 19:22:44 -07:00
while (extra_thread_index != 0) {
extra_thread_index -= 1;
self.extra_threads[extra_thread_index].wait();
}
}
while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
2019-05-25 10:07:44 -07:00
self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
2018-07-09 19:22:44 -07:00
}
},
2019-05-26 22:35:58 -07:00
.windows => {
self.os_data.io_port = try windows.CreateIoCompletionPort(
2018-07-09 19:22:44 -07:00
windows.INVALID_HANDLE_VALUE,
null,
undefined,
maxInt(windows.DWORD),
2018-07-09 19:22:44 -07:00
);
2019-05-26 22:35:58 -07:00
errdefer windows.CloseHandle(self.os_data.io_port);
2018-07-09 19:22:44 -07:00
for (self.eventfd_resume_nodes) |*eventfd_node, i| {
eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
.data = ResumeNode.EventFd{
.base = ResumeNode{
2018-07-09 19:22:44 -07:00
.id = ResumeNode.Id.EventFd,
.handle = undefined,
.overlapped = ResumeNode.overlapped_init,
2018-07-09 19:22:44 -07:00
},
// this one is for sending events
.completion_key = @ptrToInt(&eventfd_node.data.base),
},
.next = undefined,
};
self.available_eventfd_resume_nodes.push(eventfd_node);
}
if (builtin.single_threaded) {
assert(extra_thread_count == 0);
return;
}
2018-07-09 19:22:44 -07:00
var extra_thread_index: usize = 0;
errdefer {
var i: usize = 0;
while (i < extra_thread_index) : (i += 1) {
while (true) {
const overlapped = &self.final_resume_node.overlapped;
2019-05-26 22:35:58 -07:00
windows.PostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
2018-07-09 19:22:44 -07:00
break;
}
}
while (extra_thread_index != 0) {
extra_thread_index -= 1;
self.extra_threads[extra_thread_index].wait();
}
}
while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
2019-05-25 10:07:44 -07:00
self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
2018-07-09 19:22:44 -07:00
}
},
else => {},
}
}
fn deinitOsData(self: *Loop) void {
switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.linux => {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
noasync os.close(self.os_data.final_eventfd);
while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
noasync os.close(self.os_data.epollfd);
2018-07-09 19:22:44 -07:00
},
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
noasync os.close(self.os_data.kqfd);
noasync os.close(self.os_data.fs_kqfd);
2018-07-09 19:22:44 -07:00
},
2019-05-26 22:35:58 -07:00
.windows => {
windows.CloseHandle(self.os_data.io_port);
2018-07-09 19:22:44 -07:00
},
else => {},
}
}
2019-08-08 12:13:05 -07:00
/// resume_node must live longer than the anyframe that it holds a reference to.
2018-07-29 20:27:21 -07:00
/// flags must contain EPOLLET
pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void {
2019-05-25 10:07:44 -07:00
assert(flags & os.EPOLLET == os.EPOLLET);
2018-07-29 20:27:21 -07:00
self.beginOneEvent();
errdefer self.finishOneEvent();
try self.linuxModFd(
2018-07-09 19:22:44 -07:00
fd,
2019-05-25 10:07:44 -07:00
os.EPOLL_CTL_ADD,
2018-07-29 20:27:21 -07:00
flags,
2018-07-09 19:22:44 -07:00
resume_node,
);
}
2018-07-29 20:27:21 -07:00
pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void {
2019-05-25 10:07:44 -07:00
assert(flags & os.EPOLLET == os.EPOLLET);
var ev = os.linux.epoll_event{
2018-07-29 20:27:21 -07:00
.events = flags,
.data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },
2018-07-09 19:22:44 -07:00
};
2019-05-26 20:35:26 -07:00
try os.epoll_ctl(self.os_data.epollfd, op, fd, &ev);
2018-07-09 19:22:44 -07:00
}
2018-07-29 20:27:21 -07:00
pub fn linuxRemoveFd(self: *Loop, fd: i32) void {
2019-05-30 07:28:33 -07:00
os.epoll_ctl(self.os_data.epollfd, os.linux.EPOLL_CTL_DEL, fd, null) catch {};
2018-08-07 18:06:21 -07:00
self.finishOneEvent();
2018-07-09 19:22:44 -07:00
}
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
pub fn linuxWaitFd(self: *Loop, fd: i32, flags: u32) void {
assert(flags & os.EPOLLET == os.EPOLLET);
assert(flags & os.EPOLLONESHOT == os.EPOLLONESHOT);
var resume_node = ResumeNode.Basic{
.base = ResumeNode{
.id = .Basic,
.handle = @frame(),
.overlapped = ResumeNode.overlapped_init,
},
};
var need_to_delete = false;
defer if (need_to_delete) self.linuxRemoveFd(fd);
suspend {
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
if (self.linuxAddFd(fd, &resume_node.base, flags)) |_| {
need_to_delete = true;
} else |err| switch (err) {
error.FileDescriptorNotRegistered => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorIncompatibleWithEpoll => unreachable,
error.FileDescriptorAlreadyPresentInSet => unreachable, // evented writes to the same fd is not thread-safe
error.SystemResources,
error.UserResourceLimitReached,
error.Unexpected,
=> {
// Fall back to a blocking poll(). Ideally this codepath is never hit, since
// epoll should be just fine. But this is better than incorrect behavior.
var poll_flags: i16 = 0;
if ((flags & os.EPOLLIN) != 0) poll_flags |= os.POLLIN;
if ((flags & os.EPOLLOUT) != 0) poll_flags |= os.POLLOUT;
var pfd = [1]os.pollfd{os.pollfd{
.fd = fd,
.events = poll_flags,
.revents = undefined,
}};
_ = os.poll(&pfd, -1) catch |poll_err| switch (poll_err) {
error.SystemResources,
error.Unexpected,
=> {
// Even poll() didn't work. The best we can do now is sleep for a
// small duration and then hope that something changed.
std.time.sleep(1 * std.time.millisecond);
},
};
resume @frame();
},
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
}
2018-07-09 19:22:44 -07:00
}
}
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLIN);
}
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
pub fn waitUntilFdWritable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT);
}
pub fn waitUntilFdWritableOrReadable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN);
}
2019-05-25 10:07:44 -07:00
pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent {
var resume_node = ResumeNode.Basic{
.base = ResumeNode{
2018-08-07 18:06:21 -07:00
.id = ResumeNode.Id.Basic,
2019-08-11 16:53:10 -07:00
.handle = @frame(),
.overlapped = ResumeNode.overlapped_init,
},
.kev = undefined,
};
defer self.bsdRemoveKev(ident, filter);
suspend {
2018-08-07 18:06:21 -07:00
try self.bsdAddKev(&resume_node, ident, filter, fflags);
}
return resume_node.kev;
2018-08-07 18:06:21 -07:00
}
2019-08-08 12:13:05 -07:00
/// resume_node must live longer than the anyframe that it holds a reference to.
pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void {
2018-08-07 18:06:21 -07:00
self.beginOneEvent();
errdefer self.finishOneEvent();
2019-05-25 10:07:44 -07:00
var kev = os.Kevent{
2018-08-07 18:06:21 -07:00
.ident = ident,
.filter = filter,
2019-05-25 10:07:44 -07:00
.flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR,
2018-08-07 18:06:21 -07:00
.fflags = fflags,
.data = 0,
.udata = @ptrToInt(&resume_node.base),
2018-08-07 18:06:21 -07:00
};
2019-05-25 10:07:44 -07:00
const kevent_array = (*const [1]os.Kevent)(&kev);
const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
2019-05-27 11:12:50 -07:00
_ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null);
2018-08-07 18:06:21 -07:00
}
pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void {
2019-05-25 10:07:44 -07:00
var kev = os.Kevent{
2018-08-07 18:06:21 -07:00
.ident = ident,
.filter = filter,
2019-05-25 10:07:44 -07:00
.flags = os.EV_DELETE,
2018-08-07 18:06:21 -07:00
.fflags = 0,
.data = 0,
.udata = 0,
};
2019-05-25 10:07:44 -07:00
const kevent_array = (*const [1]os.Kevent)(&kev);
const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined;
2018-08-07 18:06:21 -07:00
self.finishOneEvent();
}
fn dispatch(self: *Loop) void {
while (self.available_eventfd_resume_nodes.pop()) |resume_stack_node| {
const next_tick_node = self.next_tick_queue.get() orelse {
self.available_eventfd_resume_nodes.push(resume_stack_node);
return;
};
const eventfd_node = &resume_stack_node.data;
eventfd_node.base.handle = next_tick_node.data;
switch (builtin.os) {
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.kevent);
const empty_kevs = &[0]os.Kevent{};
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
self.next_tick_queue.unget(next_tick_node);
self.available_eventfd_resume_nodes.push(resume_stack_node);
return;
};
},
2019-05-26 22:35:58 -07:00
.linux => {
// the pending count is already accounted for
2019-05-25 10:07:44 -07:00
const epoll_events = os.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT |
os.linux.EPOLLET;
2018-07-29 20:27:21 -07:00
self.linuxModFd(
eventfd_node.eventfd,
eventfd_node.epoll_op,
epoll_events,
&eventfd_node.base,
) catch {
self.next_tick_queue.unget(next_tick_node);
self.available_eventfd_resume_nodes.push(resume_stack_node);
return;
};
},
2019-05-26 22:35:58 -07:00
.windows => {
windows.PostQueuedCompletionStatus(
self.os_data.io_port,
undefined,
undefined,
&eventfd_node.base.overlapped,
) catch {
self.next_tick_queue.unget(next_tick_node);
self.available_eventfd_resume_nodes.push(resume_stack_node);
return;
};
},
else => @compileError("unsupported OS"),
}
}
}
2018-07-09 19:22:44 -07:00
/// Bring your own linked list node. This means it can't fail.
pub fn onNextTick(self: *Loop, node: *NextTickNode) void {
2018-07-29 20:27:21 -07:00
self.beginOneEvent(); // finished in dispatch()
2018-07-09 19:22:44 -07:00
self.next_tick_queue.put(node);
self.dispatch();
2018-07-09 19:22:44 -07:00
}
2018-08-02 14:04:17 -07:00
pub fn cancelOnNextTick(self: *Loop, node: *NextTickNode) void {
if (self.next_tick_queue.remove(node)) {
self.finishOneEvent();
}
}
2018-07-09 19:22:44 -07:00
pub fn run(self: *Loop) void {
self.finishOneEvent(); // the reference we start with
2018-07-09 19:22:44 -07:00
self.workerRun();
switch (builtin.os) {
2019-08-08 12:13:05 -07:00
.linux,
.macosx,
.freebsd,
.netbsd,
2019-10-22 15:06:35 -07:00
.dragonfly,
2019-08-08 13:41:38 -07:00
=> self.os_data.fs_thread.wait(),
else => {},
}
2018-07-09 19:22:44 -07:00
for (self.extra_threads) |extra_thread| {
extra_thread.wait();
}
}
2019-08-08 12:13:05 -07:00
/// Yielding lets the event loop run, starting any unstarted async operations.
2018-07-13 18:56:38 -07:00
/// Note that async operations automatically start when a function yields for any other reason,
/// for example, when async I/O is performed. This function is intended to be used only when
/// CPU bound tasks would be waiting in the event loop but never get started because no async I/O
/// is performed.
2019-08-08 12:13:05 -07:00
pub fn yield(self: *Loop) void {
suspend {
2019-08-08 12:13:05 -07:00
var my_tick_node = NextTickNode{
2018-08-02 14:04:17 -07:00
.prev = undefined,
2018-07-13 18:56:38 -07:00
.next = undefined,
2019-08-08 12:13:05 -07:00
.data = @frame(),
2018-07-13 18:56:38 -07:00
};
self.onNextTick(&my_tick_node);
2018-07-13 18:56:38 -07:00
}
}
2019-08-08 12:13:05 -07:00
/// If the build is multi-threaded and there is an event loop, then it calls `yield`. Otherwise,
/// does nothing.
pub fn startCpuBoundOperation() void {
if (builtin.single_threaded) {
2019-08-08 12:13:05 -07:00
return;
} else if (instance) |event_loop| {
event_loop.yield();
}
}
2018-07-29 20:27:21 -07:00
/// call finishOneEvent when done
pub fn beginOneEvent(self: *Loop) void {
_ = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
}
pub fn finishOneEvent(self: *Loop) void {
const prev = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);
if (prev == 1) {
// cause all the threads to stop
switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.linux => {
2019-08-08 13:41:38 -07:00
self.posixFsRequest(&self.os_data.fs_end_request);
// writing 8 bytes to an eventfd cannot fail
noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
return;
},
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
self.posixFsRequest(&self.os_data.fs_end_request);
const final_kevent = @as(*const [1]os.Kevent, &self.os_data.final_kevent);
const empty_kevs = &[0]os.Kevent{};
// cannot fail because we already added it and this just enables it
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable;
return;
},
2019-05-26 22:35:58 -07:00
.windows => {
var i: usize = 0;
while (i < self.extra_threads.len + 1) : (i += 1) {
while (true) {
const overlapped = &self.final_resume_node.overlapped;
2019-05-26 22:35:58 -07:00
windows.PostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
break;
2018-07-09 19:22:44 -07:00
}
}
return;
},
else => @compileError("unsupported OS"),
}
}
}
2018-07-09 19:22:44 -07:00
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
/// Performs an async `os.open` using a separate thread.
pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: usize) os.OpenError!os.fd_t {
var req_node = Request.Node{
.data = .{
.msg = .{
.open = .{
.path = file_path,
.flags = flags,
.mode = mode,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.open.result;
}
/// Performs an async `os.opent` using a separate thread.
pub fn openatZ(self: *Loop, fd: os.fd_t, file_path: [*:0]const u8, flags: u32, mode: usize) os.OpenError!os.fd_t {
var req_node = Request.Node{
.data = .{
.msg = .{
.openat = .{
.fd = fd,
.path = file_path,
.flags = flags,
.mode = mode,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.openat.result;
}
/// Performs an async `os.close` using a separate thread.
pub fn close(self: *Loop, fd: os.fd_t) void {
var req_node = Request.Node{
.data = .{
.msg = .{ .close = .{ .fd = fd } },
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
}
/// Performs an async `os.read` using a separate thread.
/// `fd` must block and not return EAGAIN.
pub fn read(self: *Loop, fd: os.fd_t, buf: []u8) os.ReadError!usize {
var req_node = Request.Node{
.data = .{
.msg = .{
.read = .{
.fd = fd,
.buf = buf,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.read.result;
}
/// Performs an async `os.readv` using a separate thread.
/// `fd` must block and not return EAGAIN.
pub fn readv(self: *Loop, fd: os.fd_t, iov: []const os.iovec) os.ReadError!usize {
var req_node = Request.Node{
.data = .{
.msg = .{
.readv = .{
.fd = fd,
.iov = iov,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.readv.result;
}
/// Performs an async `os.preadv` using a separate thread.
/// `fd` must block and not return EAGAIN.
pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64) os.ReadError!usize {
var req_node = Request.Node{
.data = .{
.msg = .{
.preadv = .{
.fd = fd,
.iov = iov,
.offset = offset,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.preadv.result;
}
/// Performs an async `os.write` using a separate thread.
/// `fd` must block and not return EAGAIN.
pub fn write(self: *Loop, fd: os.fd_t, bytes: []const u8) os.WriteError!void {
var req_node = Request.Node{
.data = .{
.msg = .{
.write = .{
.fd = fd,
.bytes = bytes,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.write.result;
}
/// Performs an async `os.writev` using a separate thread.
/// `fd` must block and not return EAGAIN.
2020-02-07 22:38:01 -08:00
pub fn writev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const) os.WriteError!void {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
var req_node = Request.Node{
.data = .{
.msg = .{
.writev = .{
.fd = fd,
.iov = iov,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.writev.result;
}
/// Performs an async `os.pwritev` using a separate thread.
/// `fd` must block and not return EAGAIN.
2020-02-07 22:38:01 -08:00
pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64) os.WriteError!void {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
var req_node = Request.Node{
.data = .{
.msg = .{
.pwritev = .{
.fd = fd,
.iov = iov,
.offset = offset,
.result = undefined,
},
},
.finish = .{ .TickNode = .{ .data = @frame() } },
},
};
suspend {
self.posixFsRequest(&req_node);
}
return req_node.data.msg.pwritev.result;
}
fn workerRun(self: *Loop) void {
while (true) {
while (true) {
const next_tick_node = self.next_tick_queue.get() orelse break;
self.dispatch();
resume next_tick_node.data;
self.finishOneEvent();
2018-07-09 19:22:44 -07:00
}
switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.linux => {
2018-07-09 19:22:44 -07:00
// only process 1 event so we don't steal from other threads
var events: [1]os.linux.epoll_event = undefined;
2019-05-26 20:35:26 -07:00
const count = os.epoll_wait(self.os_data.epollfd, events[0..], -1);
2018-07-09 19:22:44 -07:00
for (events[0..count]) |ev| {
const resume_node = @intToPtr(*ResumeNode, ev.data.ptr);
const handle = resume_node.handle;
const resume_node_id = resume_node.id;
switch (resume_node_id) {
2019-08-08 12:13:05 -07:00
.Basic => {},
.Stop => return,
.EventFd => {
2018-07-09 19:22:44 -07:00
const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
2019-05-25 10:07:44 -07:00
event_fd_node.epoll_op = os.EPOLL_CTL_MOD;
2018-07-09 19:22:44 -07:00
const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
self.available_eventfd_resume_nodes.push(stack_node);
},
}
resume handle;
if (resume_node_id == ResumeNode.Id.EventFd) {
self.finishOneEvent();
2018-07-09 19:22:44 -07:00
}
}
},
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
2019-05-25 10:07:44 -07:00
var eventlist: [1]os.Kevent = undefined;
const empty_kevs = &[0]os.Kevent{};
2019-05-27 11:12:50 -07:00
const count = os.kevent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
2018-07-09 19:22:44 -07:00
for (eventlist[0..count]) |ev| {
const resume_node = @intToPtr(*ResumeNode, ev.udata);
const handle = resume_node.handle;
const resume_node_id = resume_node.id;
switch (resume_node_id) {
2019-08-08 12:13:05 -07:00
.Basic => {
const basic_node = @fieldParentPtr(ResumeNode.Basic, "base", resume_node);
basic_node.kev = ev;
},
2019-08-08 12:13:05 -07:00
.Stop => return,
.EventFd => {
2018-07-09 19:22:44 -07:00
const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
self.available_eventfd_resume_nodes.push(stack_node);
},
}
resume handle;
if (resume_node_id == ResumeNode.Id.EventFd) {
self.finishOneEvent();
2018-07-09 19:22:44 -07:00
}
}
},
2019-05-26 22:35:58 -07:00
.windows => {
2018-07-09 19:22:44 -07:00
var completion_key: usize = undefined;
const overlapped = while (true) {
2018-07-09 19:22:44 -07:00
var nbytes: windows.DWORD = undefined;
var overlapped: ?*windows.OVERLAPPED = undefined;
2019-05-26 22:35:58 -07:00
switch (windows.GetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {
.Aborted => return,
.Normal => {},
.EOF => {},
.Cancelled => continue,
2018-07-09 19:22:44 -07:00
}
if (overlapped) |o| break o;
} else unreachable; // TODO else unreachable should not be necessary
const resume_node = @fieldParentPtr(ResumeNode, "overlapped", overlapped);
2018-07-09 19:22:44 -07:00
const handle = resume_node.handle;
const resume_node_id = resume_node.id;
switch (resume_node_id) {
2019-08-08 12:13:05 -07:00
.Basic => {},
.Stop => return,
.EventFd => {
2018-07-09 19:22:44 -07:00
const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
self.available_eventfd_resume_nodes.push(stack_node);
},
}
resume handle;
self.finishOneEvent();
2018-07-09 19:22:44 -07:00
},
else => @compileError("unsupported OS"),
}
}
}
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
fn posixFsRequest(self: *Loop, request_node: *Request.Node) void {
self.beginOneEvent(); // finished in posixFsRun after processing the msg
self.os_data.fs_queue.put(request_node);
switch (builtin.os) {
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake);
const empty_kevs = &[0]os.Kevent{};
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
},
2019-08-08 12:13:05 -07:00
.linux => {
2019-11-12 14:45:37 -08:00
@atomicStore(i32, &self.os_data.fs_queue_item, 1, AtomicOrder.SeqCst);
const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
switch (os.linux.getErrno(rc)) {
0 => {},
2019-05-25 10:07:44 -07:00
os.EINVAL => unreachable,
else => unreachable,
}
},
else => @compileError("Unsupported OS"),
}
}
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
fn posixFsCancel(self: *Loop, request_node: *Request.Node) void {
2018-08-07 18:06:21 -07:00
if (self.os_data.fs_queue.remove(request_node)) {
self.finishOneEvent();
}
}
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
// TODO make this whole function noasync
// https://github.com/ziglang/zig/issues/3157
fn posixFsRun(self: *Loop) void {
while (true) {
if (builtin.os == .linux) {
2019-11-12 14:45:37 -08:00
@atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst);
2018-08-07 18:06:21 -07:00
}
while (self.os_data.fs_queue.get()) |node| {
switch (node.data.msg) {
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.end => return,
.read => |*msg| {
msg.result = noasync os.read(msg.fd, msg.buf);
},
.write => |*msg| {
msg.result = noasync os.write(msg.fd, msg.bytes);
},
.writev => |*msg| {
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
msg.result = noasync os.writev(msg.fd, msg.iov);
},
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.pwritev => |*msg| {
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
msg.result = noasync os.pwritev(msg.fd, msg.iov, msg.offset);
2018-07-29 20:27:21 -07:00
},
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.preadv => |*msg| {
std lib networking improvements, especially non-blocking I/O * delete the std/event/net directory * `std.event.Loop.waitUntilFdReadable` and related functions no longer have possibility of failure. On Linux, they fall back to poll() and then fall back to sleep(). * add some missing `noasync` decorations in `std.event.Loop` * redo the `std.net.Server` API. it's quite nice now, but shutdown does not work cleanly. There is a race condition with close() that I am actively working on. * move `std.io.OutStream` to its own file to match `std.io.InStream`. I started working on making `write` integrated with evented I/O, but it got tricky so I backed off and filed #3557. However I did integrate `std.os.writev` and `std.os.pwritev` with evented I/O. * add `std.Target.stack_align` * move networking tests to `lib/std/net/test.zig` * add `std.net.tcpConnectToHost` and `std.net.tcpConnectToAddress`. * rename `error.UnknownName` to `error.UnknownHostName` within the context of DNS resolution. * add `std.os.readv`, which is integrated with evented I/O. * `std.os.preadv`, is now integrated with evented I/O. * `std.os.accept4` now asserts that ENOTSOCK and EOPNOTSUPP never occur (misuse of API), instead of returning errors. * `std.os.connect` is now integrated with evented I/O. `std.os.connect_async` is gone. Just use `std.os.connect`. * fix false positive dependency loop regarding async function frames * add more compile notes to help when dependency loops occur in determining whether a function is async. * ir: change an assert to ir_assert to make it easier to find workarounds for when such an assert is triggered. In this case it was trying to parse an IPv4 address at comptime.
2019-10-29 19:59:30 -07:00
msg.result = noasync os.preadv(msg.fd, msg.iov, msg.offset);
},
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.open => |*msg| {
msg.result = noasync os.openC(msg.path, msg.flags, msg.mode);
2018-07-29 20:27:21 -07:00
},
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.openat => |*msg| {
msg.result = noasync os.openatC(msg.fd, msg.path, msg.flags, msg.mode);
},
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
.close => |*msg| noasync os.close(msg.fd),
}
switch (node.data.finish) {
2019-08-08 12:13:05 -07:00
.TickNode => |*tick_node| self.onNextTick(tick_node),
.NoAction => {},
}
self.finishOneEvent();
}
switch (builtin.os) {
.linux => {
const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
switch (os.linux.getErrno(rc)) {
2019-05-25 10:07:44 -07:00
0, os.EINTR, os.EAGAIN => continue,
else => unreachable,
}
},
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => {
const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wait);
2019-05-25 10:07:44 -07:00
var out_kevs: [1]os.Kevent = undefined;
2019-05-27 11:12:50 -07:00
_ = os.kevent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
},
else => @compileError("Unsupported OS"),
}
}
}
2018-07-09 19:22:44 -07:00
const OsData = switch (builtin.os) {
2019-05-26 22:35:58 -07:00
.linux => LinuxOsData,
2019-10-22 15:06:35 -07:00
.macosx, .freebsd, .netbsd, .dragonfly => KEventData,
2019-05-26 22:35:58 -07:00
.windows => struct {
2018-07-09 19:22:44 -07:00
io_port: windows.HANDLE,
extra_thread_count: usize,
},
else => struct {},
2018-07-09 19:22:44 -07:00
};
const KEventData = struct {
2018-07-09 19:22:44 -07:00
kqfd: i32,
2019-05-25 10:07:44 -07:00
final_kevent: os.Kevent,
fs_kevent_wake: os.Kevent,
fs_kevent_wait: os.Kevent,
fs_thread: *Thread,
fs_kqfd: i32,
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
fs_queue: std.atomic.Queue(Request),
fs_end_request: Request.Node,
2018-07-09 19:22:44 -07:00
};
const LinuxOsData = struct {
epollfd: i32,
final_eventfd: i32,
final_eventfd_event: os.linux.epoll_event,
2019-08-08 13:41:38 -07:00
fs_thread: *Thread,
fs_queue_item: i32,
more std lib async I/O integration * `zig test` gainst `--test-evented-io` parameter and gains the ability to seamlessly run async tests. * `std.ChildProcess` opens its child process pipe with O_NONBLOCK when using evented I/O * `std.io.getStdErr()` gives a File that is blocking even in evented I/O mode. * Delete `std.event.fs`. The functionality is now merged into `std.fs` and async file system access (using a dedicated thread) is automatically handled. * `std.fs.File` can be configured to specify whether its handle is expected to block, and whether that is OK to block even when in async I/O mode. This makes async I/O work correctly for e.g. the file system as well as network. * `std.fs.File` has some deprecated functions removed. * Missing readv,writev,pread,pwrite,preadv,pwritev functions are added to `std.os` and `std.fs.File`. They are all integrated with async I/O. * `std.fs.Watch` is still bit rotted and needs to be audited in light of the new async/await syntax. * `std.io.OutStream` integrates with async I/O * linked list nodes in the std lib have default `null` values for `prev` and `next`. * Windows async I/O integration is enabled for reading/writing file handles. * Added `std.os.mode_t`. Integer sizes need to be audited. * Fixed #4403 which was causing compiler to crash. This is working towards: ./zig test ../test/stage1/behavior.zig --test-evented-io Which does not successfully build yet. I'd like to enable behavioral tests and std lib tests with --test-evented-io in the test matrix in the future, to prevent regressions.
2020-02-06 14:56:40 -08:00
fs_queue: std.atomic.Queue(Request),
fs_end_request: Request.Node,
};
pub const Request = struct {
msg: Msg,
finish: Finish,
pub const Node = std.atomic.Queue(Request).Node;
pub const Finish = union(enum) {
TickNode: Loop.NextTickNode,
NoAction,
};
pub const Msg = union(enum) {
read: Read,
write: Write,
writev: WriteV,
pwritev: PWriteV,
preadv: PReadV,
open: Open,
openat: OpenAt,
close: Close,
/// special - means the fs thread should exit
end,
pub const Read = struct {
fd: os.fd_t,
buf: []u8,
result: Error!usize,
pub const Error = os.ReadError;
};
pub const Write = struct {
fd: os.fd_t,
bytes: []const u8,
result: Error!void,
pub const Error = os.WriteError;
};
pub const WriteV = struct {
fd: os.fd_t,
iov: []const os.iovec_const,
result: Error!void,
pub const Error = os.WriteError;
};
pub const PWriteV = struct {
fd: os.fd_t,
iov: []const os.iovec_const,
offset: usize,
result: Error!void,
pub const Error = os.WriteError;
};
pub const PReadV = struct {
fd: os.fd_t,
iov: []const os.iovec,
offset: usize,
result: Error!usize,
pub const Error = os.ReadError;
};
pub const Open = struct {
path: [*:0]const u8,
flags: u32,
mode: os.mode_t,
result: Error!os.fd_t,
pub const Error = os.OpenError;
};
pub const OpenAt = struct {
fd: os.fd_t,
path: [*:0]const u8,
flags: u32,
mode: os.mode_t,
result: Error!os.fd_t,
pub const Error = os.OpenError;
};
pub const Close = struct {
fd: os.fd_t,
};
};
};
2018-07-09 19:22:44 -07:00
};
test "std.event.Loop - basic" {
// https://github.com/ziglang/zig/issues/1908
2019-08-08 12:13:05 -07:00
if (builtin.single_threaded) return error.SkipZigTest;
2018-07-09 19:41:16 -07:00
var loop: Loop = undefined;
try loop.initMultiThreaded();
2018-07-09 19:41:16 -07:00
defer loop.deinit();
2018-07-09 19:22:44 -07:00
2018-07-09 19:41:16 -07:00
loop.run();
2018-07-09 19:22:44 -07:00
}
async fn testEventLoop() i32 {
return 1234;
}
2019-08-08 12:13:05 -07:00
async fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
const value = await h;
testing.expect(value == 1234);
did_it.* = true;
}