core: remove option to support non-blocking and only allow platform to control main loop

This commit is contained in:
Joshua Holmes 2025-01-03 07:21:29 +00:00 committed by Emi Gutekanst
parent 710b5907a2
commit caf297512c
4 changed files with 15 additions and 69 deletions

View file

@ -14,25 +14,6 @@ pub fn main() !void {
var mods: Modules = undefined; var mods: Modules = undefined;
try mods.init(allocator); try mods.init(allocator);
// On some platforms, you can drive the mach.Core main loop yourself - but this isn't possible
// on all platforms. If mach.Core.non_blocking is set to true, and the platform supports
// non-blocking mode, then .mach_core.main will return without blocking. Otherwise it will block
// forever and app.run(.main) will never return.
if (mach.Core.supports_non_blocking) {
defer mods.deinit(allocator);
mach.Core.non_blocking = true;
const app = mods.get(.app);
app.run(.main);
// If you are driving the main loop yourself, you should call tick until exit.
const core = mods.get(.mach_core);
while (mods.mods.mach_core.state != .exited) {
core.run(.tick);
}
} else {
const app = mods.get(.app); const app = mods.get(.app);
app.run(.main); app.run(.main);
} }
}

View file

@ -8,26 +8,8 @@ const log = std.log.scoped(.mach);
const Core = @This(); const Core = @This();
// Whether or not you can drive the main loop in a non-blocking fashion, or if the underlying
// platform must take control and drive the main loop itself.
pub const supports_non_blocking = switch (build_options.core_platform) {
// Platforms that support non-blocking mode.
.linux => true,
.windows => true,
.null => true,
// Platforms which take control of the main loop.
.wasm => false,
.darwin => false,
};
const EventQueue = std.fifo.LinearFifo(Event, .Dynamic); const EventQueue = std.fifo.LinearFifo(Event, .Dynamic);
/// Set this to true if you intend to drive the main loop yourself.
///
/// A panic will occur if `supports_non_blocking == false` for the platform.
pub var non_blocking = false;
pub const mach_module = .mach_core; pub const mach_module = .mach_core;
pub const mach_systems = .{ .main, .init, .tick, .presentFrame, .deinit }; pub const mach_systems = .{ .main, .init, .tick, .presentFrame, .deinit };
@ -277,38 +259,13 @@ pub fn main(core: *Core, core_mod: mach.Mod(Core)) !void {
core_mod.run(core.on_tick.?); core_mod.run(core.on_tick.?);
core_mod.call(.presentFrame); core_mod.call(.presentFrame);
// If the user doesn't want mach.Core to take control of the main loop, we bail out - the next
// app tick is already scheduled to run in the future and they'll .present_frame to return
// control to us later.
if (non_blocking) {
if (!supports_non_blocking) std.debug.panic(
"mach.Core: platform {s} does not support non_blocking=true mode.",
.{@tagName(build_options.core_platform)},
);
return;
}
// The user wants mach.Core to take control of the main loop.
if (supports_non_blocking) {
while (core.state != .exited) {
try Platform.tick(core);
core_mod.run(core.on_tick.?);
core_mod.call(.presentFrame);
}
// Don't return, because Platform.run wouldn't either (marked noreturn due to underlying
// platform APIs never returning.)
std.process.exit(0);
} else {
// Platform drives the main loop. // Platform drives the main loop.
Platform.run(platform_update_callback, .{ core, core_mod }); Platform.run(platform_update_callback, .{ core, core_mod });
// Platform.run should be marked noreturn, so this shouldn't ever run. But just in case we // Platform.run is marked noreturn on some platforms, but not all, so this is here for the
// accidentally introduce a different Platform.run in the future, we put an exit here for // platforms that do return
// good measure.
std.process.exit(0); std.process.exit(0);
} }
}
fn platform_update_callback(core: *Core, core_mod: mach.Mod(Core)) !bool { fn platform_update_callback(core: *Core, core_mod: mach.Mod(Core)) !bool {
// TODO(core)(slimsag): consider execution order of mach.Core (e.g. creating a new window // TODO(core)(slimsag): consider execution order of mach.Core (e.g. creating a new window

View file

@ -58,6 +58,10 @@ backend: Backend,
const MISSING_FEATURES_X11 = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/cursor" }; const MISSING_FEATURES_X11 = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/cursor" };
const MISSING_FEATURES_WAYLAND = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/cursor" }; const MISSING_FEATURES_WAYLAND = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/cursor" };
pub fn run(comptime on_each_update_fn: anytype, args_tuple: std.meta.ArgsTuple(@TypeOf(on_each_update_fn))) void {
while (@call(.auto, on_each_update_fn, args_tuple) catch false) {}
}
pub fn tick(core: *Core) !void { pub fn tick(core: *Core) !void {
var windows = core.windows.slice(); var windows = core.windows.slice();
while (windows.next()) |window_id| { while (windows.next()) |window_id| {

View file

@ -33,6 +33,10 @@ pub const Context = struct {
window_id: mach.ObjectID, window_id: mach.ObjectID,
}; };
pub fn run(comptime on_each_update_fn: anytype, args_tuple: std.meta.ArgsTuple(@TypeOf(on_each_update_fn))) void {
while (@call(.auto, on_each_update_fn, args_tuple) catch false) {}
}
pub fn tick(core: *Core) !void { pub fn tick(core: *Core) !void {
var windows = core.windows.slice(); var windows = core.windows.slice();
while (windows.next()) |window_id| { while (windows.next()) |window_id| {