Application Context Implementation #4
| @ -21,7 +21,7 @@ test { | ||||
|     _ = sys; | ||||
| } | ||||
| 
 | ||||
| fn run(app: *sys.App, graphics: *sys.GraphicsContext) anyerror!void { | ||||
| fn run(app: *sys.AppContext, graphics: *sys.GraphicsContext) anyerror!void { | ||||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
| 
 | ||||
|     defer _ = gpa.deinit(); | ||||
|  | ||||
							
								
								
									
										107
									
								
								src/sys.zig
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/sys.zig
									
									
									
									
									
								
							| @ -12,7 +12,7 @@ const std = @import("std"); | ||||
| /// | ||||
| /// A thread-safe platform abstraction over multiplexing system I/O processing and event handling. | ||||
| /// | ||||
| pub const App = opaque { | ||||
| pub const AppContext = opaque { | ||||
|     /// | ||||
|     /// Linked list of asynchronous messages chained together to be processed by the work processor. | ||||
|     /// | ||||
| @ -71,13 +71,13 @@ pub const App = opaque { | ||||
|         }; | ||||
| 
 | ||||
|         /// | ||||
|         /// Casts `app` to a [Implementation] reference. | ||||
|         /// Casts `app_context` to a [Implementation] reference. | ||||
|         /// | ||||
|         /// *Note* that if `app` does not have the same alignment as [Implementation], safety- | ||||
|         /// *Note* that if `app_context` does not have the same alignment as [Implementation], safety- | ||||
|         /// checked undefined behavior will occur. | ||||
|         /// | ||||
|         fn cast(app: *App) *Implementation { | ||||
|             return @ptrCast(*Implementation, @alignCast(@alignOf(Implementation), app)); | ||||
|         fn cast(app_context: *AppContext) *Implementation { | ||||
|             return @ptrCast(*Implementation, @alignCast(@alignOf(Implementation), app_context)); | ||||
|         } | ||||
| 
 | ||||
|         /// | ||||
| @ -90,7 +90,7 @@ pub const App = opaque { | ||||
|                 .kind = .quit, | ||||
|             }; | ||||
| 
 | ||||
|             @ptrCast(*App, implementation).schedule(&message); | ||||
|             @ptrCast(*AppContext, implementation).schedule(&message); | ||||
| 
 | ||||
|             { | ||||
|                 var status = @as(c_int, 0); | ||||
| @ -132,7 +132,7 @@ pub const App = opaque { | ||||
|         /// occured. | ||||
|         /// | ||||
|         fn processTasks(userdata: ?*anyopaque) callconv(.C) c_int { | ||||
|             const implementation = Implementation.cast(@ptrCast(*App, userdata orelse unreachable)); | ||||
|             const implementation = Implementation.cast(@ptrCast(*AppContext, userdata orelse unreachable)); | ||||
| 
 | ||||
|             while (true) { | ||||
|                 _ = ext.SDL_LockMutex(implementation.message_mutex); | ||||
| @ -164,7 +164,9 @@ pub const App = opaque { | ||||
|         fn start(implementation: *Implementation) StartError!void { | ||||
|             if (implementation.message_thread != null) return error.AlreadyStarted; | ||||
| 
 | ||||
|             implementation.message_thread = ext.SDL_CreateThread(processTasks, "File System Worker", implementation) orelse { | ||||
|             implementation.message_thread = ext.SDL_CreateThread(processTasks, | ||||
|                 "File System Worker", implementation) orelse { | ||||
| 
 | ||||
|                 ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, | ||||
|                     "Failed to create file-system work processor"); | ||||
| 
 | ||||
| @ -176,16 +178,16 @@ pub const App = opaque { | ||||
|     /// | ||||
|     /// Returns a reference to the currently loaded data file-system. | ||||
|     /// | ||||
|     pub fn data(app: *App) *const FileSystem { | ||||
|         return &Implementation.cast(app).data_file_system; | ||||
|     pub fn data(app_context: *AppContext) *const FileSystem { | ||||
|         return &Implementation.cast(app_context).data_file_system; | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
|     /// Enqueues `message` to the message processor of `app` to be processed at a later, non- | ||||
|     /// Enqueues `message` to the message processor of `app_context` to be processed at a later, non- | ||||
|     /// deterministic point. | ||||
|     /// | ||||
|     pub fn schedule(app: *App, message: *Message) void { | ||||
|         const implementation = Implementation.cast(app); | ||||
|     pub fn schedule(app_context: *AppContext, message: *Message) void { | ||||
|         const implementation = Implementation.cast(app_context); | ||||
| 
 | ||||
|         // TODO: Error check these. | ||||
|         _ = ext.SDL_LockMutex(implementation.message_mutex); | ||||
| @ -205,8 +207,8 @@ pub const App = opaque { | ||||
|     /// | ||||
|     /// Returns a reference to the currently loaded user file-system. | ||||
|     /// | ||||
|     pub fn user(app: *App) *const FileSystem { | ||||
|         return &Implementation.cast(app).user_file_system; | ||||
|     pub fn user(app_context: *AppContext) *const FileSystem { | ||||
|         return &Implementation.cast(app_context).user_file_system; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| @ -236,7 +238,7 @@ pub const FileAccess = opaque { | ||||
|     /// Freeing an invalid `file_access` has no effect on the file and logs a warning over the | ||||
|     /// wasted effort. | ||||
|     /// | ||||
|     pub fn close(file_access: *FileAccess, app: *App) void { | ||||
|     pub fn close(file_access: *FileAccess, app_context: *AppContext) void { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
| 
 | ||||
| @ -253,7 +255,7 @@ pub const FileAccess = opaque { | ||||
| 
 | ||||
|         var task = Task{.file_access = file_access}; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -262,7 +264,7 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
| @ -271,7 +273,7 @@ pub const FileAccess = opaque { | ||||
|     /// Returns the number of bytes into the file that the cursor is relative to its beginning or a | ||||
|     /// [Error] on failure. | ||||
|     /// | ||||
|     pub fn queryCursor(file_access: *FileAccess, app: *App) Error!u64 { | ||||
|     pub fn queryCursor(file_access: *FileAccess, app_context: *AppContext) Error!u64 { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
|             result: Error!u64, | ||||
| @ -300,7 +302,7 @@ pub const FileAccess = opaque { | ||||
|             .result = error.FileInaccessible, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -309,7 +311,7 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
| 
 | ||||
|         return task.result; | ||||
|     } | ||||
| @ -320,7 +322,7 @@ pub const FileAccess = opaque { | ||||
|     /// Returns the current length of the file at the time of the operation or a [Error] if the file | ||||
|     /// failed to be queried. | ||||
|     /// | ||||
|     pub fn queryLength(file_access: *FileAccess, app: *App) Error!u64 { | ||||
|     pub fn queryLength(file_access: *FileAccess, app_context: *AppContext) Error!u64 { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
|             result: Error!usize, | ||||
| @ -349,7 +351,7 @@ pub const FileAccess = opaque { | ||||
|             .result = error.FileInaccessible, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -358,18 +360,18 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
| 
 | ||||
|         return task.result; | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
|     /// Attempts to read `file_access` from the its current position into `buffer`, while using | ||||
|     /// `app` as the execution context. | ||||
|     /// `app_context` as the execution context. | ||||
|     /// | ||||
|     /// Returns the number of bytes that were available to be read, otherwise an [Error] on failure. | ||||
|     /// | ||||
|     pub fn read(file_access: *FileAccess, app: *App, buffer: []u8) Error!usize { | ||||
|     pub fn read(file_access: *FileAccess, app_context: *AppContext, buffer: []u8) Error!usize { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
|             buffer: []u8, | ||||
| @ -401,7 +403,7 @@ pub const FileAccess = opaque { | ||||
|             .result = error.FileInaccessible, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -410,18 +412,18 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
| 
 | ||||
|         return task.result; | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
|     /// Attempts to seek `file_access` from the beginning of the file to `cursor` bytes while using | ||||
|     /// `app` as the execution context. | ||||
|     /// `app_context` as the execution context. | ||||
|     /// | ||||
|     /// Returns [Error] on failure. | ||||
|     /// | ||||
|     pub fn seek(file_access: *FileAccess, app: *App, cursor: u64) Error!void { | ||||
|     pub fn seek(file_access: *FileAccess, app_context: *AppContext, cursor: u64) Error!void { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
|             cursor: u64, | ||||
| @ -458,7 +460,7 @@ pub const FileAccess = opaque { | ||||
|             .result = error.FileInaccessible, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -467,18 +469,18 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
| 
 | ||||
|         return task.result; | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
|     /// Attempts to seek `file_access` to the end of the file while using `app` as the execution | ||||
|     /// Attempts to seek `file_access` to the end of the file while using `app_context` as the execution | ||||
|     /// context. | ||||
|     /// | ||||
|     /// Returns [Error] on failure. | ||||
|     /// | ||||
|     pub fn seekToEnd(file_access: *FileAccess, app: *App) Error!void { | ||||
|     pub fn seekToEnd(file_access: *FileAccess, app_context: *AppContext) Error!void { | ||||
|         const Task = struct { | ||||
|             file_access: *FileAccess, | ||||
|             result: Error!void, | ||||
| @ -505,7 +507,7 @@ pub const FileAccess = opaque { | ||||
|             .result = error.FileInaccessible, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -514,7 +516,7 @@ pub const FileAccess = opaque { | ||||
|             }}, | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
| 
 | ||||
|         return task.result; | ||||
|     } | ||||
| @ -593,15 +595,15 @@ pub const FileSystem = union(enum) { | ||||
| 
 | ||||
|         /// | ||||
|         /// Attempts to open the file identified by `path` with `mode` as the mode for opening the | ||||
|         /// file and `app` as the execution context. | ||||
|         /// file and `app_context` as the execution context. | ||||
|         /// | ||||
|         /// Returns a [FileAccess] reference that provides access to the file referenced by `path` | ||||
|         /// or a [OpenError] if it failed. | ||||
|         /// | ||||
|         pub fn open(path: Path, app: *App, mode: OpenMode) OpenError!*FileAccess { | ||||
|         pub fn open(path: Path, app_context: *AppContext, mode: OpenMode) OpenError!*FileAccess { | ||||
|             const Task = struct { | ||||
|                 path: *const FileSystem.Path, | ||||
|                 app: *App, | ||||
|                 app_context: *AppContext, | ||||
|                 mode: OpenMode, | ||||
|                 result: OpenError!*FileAccess, | ||||
| 
 | ||||
| @ -738,11 +740,11 @@ pub const FileSystem = union(enum) { | ||||
|             var task = Task{ | ||||
|                 .mode = mode, | ||||
|                 .path = &path, | ||||
|                 .app = app, | ||||
|                 .app_context = app_context, | ||||
|                 .result = error.FileNotFound, | ||||
|             }; | ||||
| 
 | ||||
|             var message = App.Message{ | ||||
|             var message = AppContext.Message{ | ||||
|                 .frame = @frame(), | ||||
| 
 | ||||
|                 .kind = .{.task = .{ | ||||
| @ -751,7 +753,7 @@ pub const FileSystem = union(enum) { | ||||
|                 }}, | ||||
|             }; | ||||
| 
 | ||||
|             suspend app.schedule(&message); | ||||
|             suspend app_context.schedule(&message); | ||||
| 
 | ||||
|             return task.result; | ||||
|         } | ||||
| @ -863,7 +865,7 @@ pub const GraphicsContext = opaque { | ||||
| /// Returns a graphics runner that uses `Errors` as its error set. | ||||
| /// | ||||
| pub fn GraphicsRunner(comptime Errors: type) type { | ||||
|     return fn (*App, *GraphicsContext) callconv(.Async) Errors!void; | ||||
|     return fn (*AppContext, *GraphicsContext) callconv(.Async) Errors!void; | ||||
| } | ||||
| 
 | ||||
| /// | ||||
| @ -882,10 +884,10 @@ pub const Log = enum(u32) { | ||||
|     warning = ext.SDL_LOG_PRIORITY_WARN, | ||||
| 
 | ||||
|     /// | ||||
|     /// Writes `utf8_message` as the log kind identified by `log` with `app` as the execution | ||||
|     /// Writes `utf8_message` as the log kind identified by `log` with `app_context` as the execution | ||||
|     /// context. | ||||
|     /// | ||||
|     pub fn write(log: Log, app: *App, utf8_message: []const u8) void { | ||||
|     pub fn write(log: Log, app_context: *AppContext, utf8_message: []const u8) void { | ||||
|         const Task = struct { | ||||
|             log: Log, | ||||
|             utf8_message: []const u8, | ||||
| @ -905,7 +907,7 @@ pub const Log = enum(u32) { | ||||
|             .utf8_message = utf8_message, | ||||
|         }; | ||||
| 
 | ||||
|         var message = App.Message{ | ||||
|         var message = AppContext.Message{ | ||||
|             .frame = @frame(), | ||||
| 
 | ||||
|             .kind = .{.task = .{ | ||||
| @ -914,7 +916,7 @@ pub const Log = enum(u32) { | ||||
|             }} | ||||
|         }; | ||||
| 
 | ||||
|         suspend app.schedule(&message); | ||||
|         suspend app_context.schedule(&message); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| @ -972,15 +974,14 @@ pub fn runGraphics(comptime Error: anytype, | ||||
|     defer ext.SDL_DestroyRenderer(renderer); | ||||
| 
 | ||||
|     const user_path_prefix = ext.SDL_GetPrefPath("ona", "ona") orelse { | ||||
|         ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, | ||||
|             "Failed to load user path"); | ||||
|         ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, "Failed to load user path"); | ||||
| 
 | ||||
|         return error.InitFailure; | ||||
|     }; | ||||
| 
 | ||||
|     defer ext.SDL_free(user_path_prefix); | ||||
| 
 | ||||
|     var app = App.Implementation.init("./data.oar", user_path_prefix | ||||
|     var app_context = AppContext.Implementation.init("./data.oar", user_path_prefix | ||||
|         [0 .. std.mem.len(user_path_prefix)]) catch |err| { | ||||
| 
 | ||||
|         ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, switch (err) { | ||||
| @ -992,9 +993,9 @@ pub fn runGraphics(comptime Error: anytype, | ||||
|         return error.InitFailure; | ||||
|     }; | ||||
| 
 | ||||
|     defer app.deinit(); | ||||
|     defer app_context.deinit(); | ||||
| 
 | ||||
|     app.start() catch |err| { | ||||
|     app_context.start() catch |err| { | ||||
|         ext.SDL_LogCritical(ext.SDL_LOG_CATEGORY_APPLICATION, switch (err) { | ||||
|             // Not possible for it to have already been started. | ||||
|             error.AlreadyStarted => unreachable, | ||||
| @ -1010,5 +1011,5 @@ pub fn runGraphics(comptime Error: anytype, | ||||
|         }, | ||||
|     }; | ||||
| 
 | ||||
|     return run(@ptrCast(*App, &app), @ptrCast(*GraphicsContext, &graphics_context)); | ||||
|     return run(@ptrCast(*AppContext, &app_context), @ptrCast(*GraphicsContext, &graphics_context)); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user