Handle timeout of transactions that take too long

This commit is contained in:
Isaac Freund 2020-03-29 16:56:30 +02:00
parent f5304237b5
commit d9d9388978
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 38 additions and 5 deletions

View File

@ -31,6 +31,9 @@ pub const Root = struct {
// A value of 0 means there is no current transaction. // A value of 0 means there is no current transaction.
pending_count: u32, pending_count: u32,
/// Handles timeout of transactions
transaction_timer: ?*c.wl_event_source,
pub fn init(self: *Self, server: *Server) !void { pub fn init(self: *Self, server: *Server) !void {
self.server = server; self.server = server;
@ -216,7 +219,27 @@ pub const Root = struct {
} }
} }
// TODO: start a timer and handle timeout waiting for all clients to ack if (self.pending_count > 0) {
// TODO: log failure to create timer and commit immediately
self.transaction_timer = c.wl_event_loop_add_timer(
self.server.wl_event_loop,
handle_timeout,
self,
);
// Set timeout to 200ms
if (c.wl_event_source_timer_update(self.transaction_timer, 200) == -1) {
// TODO: handle failure
}
}
}
fn handle_timeout(data: ?*c_void) callconv(.C) c_int {
const root = @ptrCast(*Root, @alignCast(@alignOf(*Root), data));
// TODO: log warning
root.commitTransaction();
return 0;
} }
pub fn notifyConfigured(self: *Self) void { pub fn notifyConfigured(self: *Self) void {
@ -228,15 +251,20 @@ pub const Root = struct {
/// Apply the pending state and drop stashed buffers. This means that /// Apply the pending state and drop stashed buffers. This means that
/// the next frame drawn will be the post-transaction state of the /// the next frame drawn will be the post-transaction state of the
/// layout. Must only be called after all clients have configured for /// layout. Should only be called after all clients have configured for
/// the new layout. /// the new layout. If called early imperfect frames may be drawn.
fn commitTransaction(self: *Self) void { fn commitTransaction(self: *Self) void {
// TODO: apply damage properly // TODO: apply damage properly
// Ensure this is set to 0 to avoid entering invalid state (e.g. if called due to timeout)
self.pending_count = 0;
var it = self.views.first; var it = self.views.first;
while (it) |node| : (it = node.next) { while (it) |node| : (it = node.next) {
const view = &node.data; const view = &node.data;
// TODO: handle views that timed out // Ensure that all pending state is cleared
view.pending_serial = null;
view.current_state = view.pending_state; view.current_state = view.pending_state;
view.dropStashedBuffer(); view.dropStashedBuffer();
} }

View File

@ -14,6 +14,7 @@ pub const Server = struct {
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
wl_display: *c.wl_display, wl_display: *c.wl_display,
wl_event_loop: *c.wl_event_loop,
wlr_backend: *c.wlr_backend, wlr_backend: *c.wlr_backend,
wlr_renderer: *c.wlr_renderer, wlr_renderer: *c.wlr_renderer,
@ -30,11 +31,15 @@ pub const Server = struct {
self.allocator = allocator; self.allocator = allocator;
// The Wayland display is managed by libwayland. It handles accepting // The Wayland display is managed by libwayland. It handles accepting
// clients from the Unix socket, manging Wayland globals, and so on. // clients from the Unix socket, managing Wayland globals, and so on.
self.wl_display = c.wl_display_create() orelse self.wl_display = c.wl_display_create() orelse
return error.CantCreateWlDisplay; return error.CantCreateWlDisplay;
errdefer c.wl_display_destroy(self.wl_display); errdefer c.wl_display_destroy(self.wl_display);
// Should never return null if the display was created successfully
self.wl_event_loop = c.wl_display_get_event_loop(self.wl_display) orelse
return error.CantGetEventLoop;
// The wlr_backend abstracts the input/output hardware. Autocreate chooses // The wlr_backend abstracts the input/output hardware. Autocreate chooses
// the best option based on the environment, for example DRM when run from // the best option based on the environment, for example DRM when run from
// a tty or wayland if WAYLAND_DISPLAY is set. // a tty or wayland if WAYLAND_DISPLAY is set.