allocator: std.mem.Allocator = undefined, timeLeft: f64 = 5.0, pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "Headless"); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); self.* = .{ .allocator = allocator, }; return self; } pub fn prepare(self: *@This()) !void { try self.testThing(); } pub fn tick(self: *@This(), dt: f64) void { // std.Thread.sleep(1000_000); self.timeLeft -= dt; if (self.timeLeft < 0) core.exitNow(); const start = core.getEngineTime(); // wait 10 ms while (core.getEngineTime() - start < 0.010) { std.Thread.sleep(10_000_000); } } pub fn deinit(self: *@This()) void { self.allocator.destroy(self); } const Src = std.builtin.SourceLocation; pub fn Barrier(src: Src) type { return struct { pub const Src = src; pub var count: u32 = 0; pub var generation: u32 = 0; pub var mutex: std.Thread.Mutex = .{}; pub var cv: std.Thread.Condition = .{}; pub fn sync(threadId: u32) !void { _ = threadId; const barrierCount = core.getBarrierCount(); mutex.lock(); defer mutex.unlock(); count += 1; if (count == barrierCount) { // 2 second timeout count = 0; generation += 1; cv.broadcast(); } else { try cv.timedWait(&mutex, 1000 * 1000 * 1000 * 2); } } }; } const MultiJob = struct { pub var WorkGroupData = WorkGroupData.from(@This()); threadId: u32 = 0, threadName: []const u8, pub var cv: std.Thread.Condition = .{}; pub var mutex: std.Thread.Mutex = .{}; pub fn func(ctx: @This(), job: *core.JobContext) void { _ = job; core.tracy.SetThreadName(@ptrCast(ctx.threadName.ptr)); ctx.loop() catch {}; if (core.getEngine().isShuttingDown()) {} } pub fn loop(ctx: @This()) !void { while (!core.getEngine().isShuttingDown()) { try Barrier(@src()).sync(ctx.threadId); try ctx.tick(); if (ctx.threadId == 0) { const z = core.tracy.ZoneN(@src(), "Thread 0 sleep"); defer z.End(); core.waitSeconds(0.01); } } } pub fn tick(ctx: @This()) !void { const z = core.tracy.ZoneN(@src(), "MultiJob Tick"); defer z.End(); // std.Thread.sleep(100_000 * ctx.threadId); try Barrier(@src()).sync(ctx.threadId); } }; pub fn testThing(self: *@This()) !void { _ = self; const workerCount = 16; core.setBarrierCount(workerCount); for (0..workerCount) |i| { const name = try std.fmt.allocPrintZ(std.heap.c_allocator, "MultiJob{d}", .{i}); try core.dispatchJob(MultiJob{ .threadName = name, .threadId = @intCast(i) }); } } pub fn main() anyerror!void { var spec = try backlog.getSpec("headless"); // try spec.put("useGPA", .{ .boolean = false }); _ = backlog.startEngine(&NeonObjectTable, &spec); } const std = @import("std"); const backlog = @import("backlog"); const core = backlog.core;