With latest zig master i tried playing with threaded and evented. I tried copying code from main.zig from zig compiler. But the threaded variation seems to segfault. .evented seems to work. is there any working sample I can look at to learn about how it should be used ?
const builtin = @import("builtin");
const native_os = builtin.os.tag;
const std = @import("std");
const Io = std.Io;
const mem = std.mem;
const Allocator = mem.Allocator;
const use_debug_allocator = false;
const mem_leak_frames = 200;
const IoMode = enum {
threaded, evented
};
const io_mode: IoMode = .threaded;
const RootAllocator = if (use_debug_allocator) std.heap.DebugAllocator(.{
.stack_trace_frames = mem_leak_frames,
.thread_safe = switch (io_mode) {
.threaded => true,
.evented => false,
},
}) else struct {
pub const init: RootAllocator = .{};
pub fn allocator(_: RootAllocator) Allocator {
if (native_os == .wasi) return std.heap.wasm_allocator;
if (builtin.link_libc) return std.heap.c_allocator;
return std.heap.smp_allocator;
}
pub fn deinit(_: RootAllocator) std.heap.Check {
return .ok;
}
};
const IoImpl = switch (io_mode) {
.threaded => Io.Threaded,
.evented => Io.Evented,
};
const thread_stack_size = 2000;
fn writeAll(io: Io, file: std.Io.File, data: []const u8) !void {
var buffer: [1024]u8 = undefined;
var writer: std.Io.File.Writer = .initStreaming(file, io, &buffer);
const w = &writer.interface;
try w.writeAll(data);
try writer.end();
}
fn saveFile2(io: Io, data: []const u8, name: []const u8) !void {
const file = try Io.Dir.cwd().createFile(io, name, .{});
defer file.close(io);
try writeAll(io, file, data);
// var buffer: [1024]u8 = undefined;
// var writer: std.Io.File.Writer = .initStreaming(file, io, &buffer);
// const w = &writer.interface;
// try w.writeAll(data);
// try file.writeAll(io, data);
}
fn saveData4(io: Io, data: []const u8) !void {
var a_future = io.async(saveFile2, .{io, data, "saveA.txt"});
defer a_future.cancel(io) catch {};
var b_future = io.async(saveFile2, .{io, data, "saveB.txt"});
defer b_future.cancel(io) catch {};
// We could decide to cancel the current task
// and everything would be realeased correctly.
// if (true) return error.Canceled;
try a_future.await(io);
try b_future.await(io);
// const out: Io.File = .stdout();
try writeAll(io, .stdout(), "save complete");
}
pub fn main(init: std.process.Init.Minimal) !void {
var root_allocator: RootAllocator = .init;
defer _ = root_allocator.deinit();
const root_gpa = root_allocator.allocator();
var io_impl: IoImpl = undefined;
switch (io_mode) {
.threaded => io_impl = .init(root_gpa, .{
.stack_size = thread_stack_size,
.argv0 = .init(init.args),
.environ = init.environ,
}),
.evented => try io_impl.init(root_gpa, .{
.argv0 = .init(init.args),
.environ = init.environ,
.backing_allocator_needs_mutex = use_debug_allocator,
}),
}
defer io_impl.deinit();
const io = io_impl.io();
// const gpa = switch (io_mode) {
// .threaded => root_gpa,
// .evented => io_impl.allocator(),
// };
try saveData4(io, "data");
}