From 584f892e4d17426233ff7b97773c98f96a5a2e2d Mon Sep 17 00:00:00 2001 From: kayomn Date: Sat, 1 Oct 2022 21:12:12 +0100 Subject: [PATCH] Support idling in file system message processor --- src/sys.zig | 168 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 108 insertions(+), 60 deletions(-) diff --git a/src/sys.zig b/src/sys.zig index 8f86a17..94a87ec 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -19,6 +19,8 @@ pub const EventLoop = opaque { frame: anyframe, request: union(enum) { + exit, + close: struct { file_access: *FileAccess, }, @@ -55,6 +57,7 @@ pub const EventLoop = opaque { const Implementation = struct { user_prefix: []const u8, file_system_semaphore: *ext.SDL_sem, + file_system_mutex: *ext.SDL_mutex, file_system_thread: *ext.SDL_Thread, file_system_messages: ?*FileSystemMessage = null, @@ -107,13 +110,18 @@ pub const EventLoop = opaque { pub fn enqueueFileSystemMessage(event_loop: *EventLoop, message: *FileSystemMessage) void { const implementation = Implementation.cast(event_loop); + // TODO: Error check this. + _ = ext.SDL_LockMutex(implementation.file_system_mutex); + if (implementation.file_system_messages) |messages| { messages.next = message; } else { implementation.file_system_messages = message; } - // TODO: Post message to FS thread to perform task. + // TODO: Error check these. + _ = ext.SDL_UnlockMutex(implementation.file_system_mutex); + _ = ext.SDL_SemPost(implementation.file_system_semaphore); } /// @@ -153,69 +161,74 @@ pub const EventLoop = opaque { fn processFileSystemMessages(data: ?*anyopaque) callconv(.C) c_int { const implementation = Implementation.cast(@ptrCast(*EventLoop, data orelse unreachable)); - while (implementation.file_system_messages) |messages| { - switch (messages.request) { - .open => |*open_request| { - switch (open_request.path.file_system) { - .data => { - // TODO: Implement - open_request.result = error.NotFound; - }, + while (true) { + while (implementation.file_system_messages) |messages| { + switch (messages.request) { + .exit => return 0, - .user => { - var path_buffer = std.mem.zeroes([4096]u8); - var path = stack.Fixed(u8){.buffer = path_buffer[0 .. ]}; - - path.pushAll(implementation.user_prefix) catch { - open_request.result = error.BadFileSystem; - - continue; - }; - - if (!open_request.path.write(path.writer())) { + .open => |*open_request| { + switch (open_request.path.file_system) { + .data => { + // TODO: Implement open_request.result = error.NotFound; + }, - continue; - } + .user => { + var path_buffer = std.mem.zeroes([4096]u8); + var path = stack.Fixed(u8){.buffer = path_buffer[0 .. ]}; - if (ext.SDL_RWFromFile(&path_buffer, switch (open_request.mode) { - .readonly => "rb", - .overwrite => "wb", - .append => "ab", - })) |rw_ops| { - open_request.result = @ptrCast(*FileAccess, rw_ops); - } else { - open_request.result = error.NotFound; - } - }, - } - }, + path.pushAll(implementation.user_prefix) catch { + open_request.result = error.BadFileSystem; - .close => |*close_request| { - // Don't care if this doesn't work. - _ = ext.SDL_RWclose(@ptrCast(*ext.SDL_RWops, @alignCast( - @alignOf(ext.SDL_RWops), close_request.file_access))); - }, + continue; + }; - .read_file => |read_request| { - _ = read_request; - }, + if (!open_request.path.write(path.writer())) { + open_request.result = error.NotFound; - .seek_file => |seek_request| { - _ = seek_request; - }, + continue; + } - .tell_file => |tell_request| { - _ = tell_request; - }, + if (ext.SDL_RWFromFile(&path_buffer, switch (open_request.mode) { + .readonly => "rb", + .overwrite => "wb", + .append => "ab", + })) |rw_ops| { + open_request.result = @ptrCast(*FileAccess, rw_ops); + } else { + open_request.result = error.NotFound; + } + }, + } + }, + + .close => |*close_request| { + // Don't care if this doesn't work. + _ = ext.SDL_RWclose(@ptrCast(*ext.SDL_RWops, @alignCast( + @alignOf(ext.SDL_RWops), close_request.file_access))); + }, + + .read_file => |read_request| { + _ = read_request; + }, + + .seek_file => |seek_request| { + _ = seek_request; + }, + + .tell_file => |tell_request| { + _ = tell_request; + }, + } + + resume messages.frame; + + implementation.file_system_messages = messages.next; } - resume messages.frame; - - implementation.file_system_messages = messages.next; + // TODO: Error check this. + _ = ext.SDL_SemWait(implementation.file_system_semaphore); } - - return 0; } /// @@ -279,7 +292,7 @@ pub const EventLoop = opaque { }; /// -/// +/// File-system agnostic abstraction for manipulating a file. /// pub const FileAccess = opaque { /// @@ -449,7 +462,7 @@ pub fn GraphicsRunner(comptime Errors: type) type { /// pub fn runGraphics(comptime Errors: anytype, run: GraphicsRunner(Errors)) Errors!void { if (ext.SDL_Init(ext.SDL_INIT_EVERYTHING) != 0) { - ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL2 runtime"); + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize runtime"); return error.InitFailure; } @@ -473,7 +486,7 @@ pub fn runGraphics(comptime Errors: anytype, run: GraphicsRunner(Errors)) Errors var flags = @as(u32, 0); break: create_window ext.SDL_CreateWindow("Ona", pos, pos, 640, 480, flags) orelse { - ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to load SDL2 window"); + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to create window"); return error.InitFailure; }; @@ -485,7 +498,7 @@ pub fn runGraphics(comptime Errors: anytype, run: GraphicsRunner(Errors)) Errors var flags = @as(u32, 0); break: create_renderer ext.SDL_CreateRenderer(window, -1, flags) orelse { - ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to load SDL2 renderer"); + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to create renderer"); return error.InitFailure; }; @@ -494,16 +507,36 @@ pub fn runGraphics(comptime Errors: anytype, run: GraphicsRunner(Errors)) Errors defer ext.SDL_DestroyRenderer(renderer); var event_loop = EventLoop.Implementation{ - .file_system_semaphore = ext.SDL_CreateSemaphore(0) orelse return error.InitFailure, + .file_system_semaphore = ext.SDL_CreateSemaphore(0) orelse { + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, + "Failed to create file-system work scheduler"); + + return error.InitFailure; + }, + + .file_system_mutex = ext.SDL_CreateMutex() orelse { + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, + "Failed to create file-system work lock"); + + return error.InitFailure; + }, + .file_system_thread = unreachable, .user_prefix = pref_path, }; - event_loop.file_system_thread = ext.SDL_CreateThread(EventLoop.processFileSystemMessages, - "File System Worker", &event_loop) orelse return error.InitFailure; + event_loop.file_system_thread = ext.SDL_CreateThread( + EventLoop.processFileSystemMessages, "File System Worker", &event_loop) orelse { + + ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, + "Failed to create file-system work processor"); + + return error.InitFailure; + }; defer { ext.SDL_DestroyThread(event_loop.file_system_thread); + ext.SDL_DestroySemaphore(event_loop.file_system_mutex); ext.SDL_DestroySemaphore(event_loop.file_system_semaphore); } @@ -513,5 +546,20 @@ pub fn runGraphics(comptime Errors: anytype, run: GraphicsRunner(Errors)) Errors }, }; + var message = EventLoop.FileSystemMessage{ + .frame = @frame(), + .request = .exit, + }; + + @ptrCast(*EventLoop, event_loop).enqueueFileSystemMessage(&message); + + var status = @as(c_int, 0); + + ext.SDL_WaitThread(event_loop.file_system_thread, &status); + + if (status != 0) { + // TODO: Error check this. + } + return run(@ptrCast(*EventLoop, &event_loop), @ptrCast(*GraphicsContext, &graphics_context)); }