From 4abc56bd6d476cf386fcc998d40e3d7753a2b03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 17 Nov 2011 16:46:36 -0500 Subject: [PATCH] Introduce wl_resource_queue_event() for sending events later Some events, such as the display.delete_id, aren't very urgent and we would like to not always send them immdiately and cause an unnecessary context switch. The wl_resource_queue_event() function will place the event in the connection output buffer but not request the main loop to poll for writable. The effect is that the event will just sit in the output buffer until a more important event comes around and requires flushing. --- src/connection.c | 30 ++++++++++++++++++++++++++++-- src/connection.h | 2 ++ src/wayland-client.c | 4 ---- src/wayland-server.c | 26 ++++++++++++++++++++++++-- src/wayland-server.h | 2 ++ 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/connection.c b/src/connection.c index 4230f7d..5a7ec2e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -65,6 +65,7 @@ struct wl_connection { void *data; wl_connection_update_func_t update; struct wl_closure receive_closure, send_closure; + int write_signalled; }; union wl_value { @@ -285,10 +286,13 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask) close_fds(&connection->fds_out); connection->out.tail += len; - if (connection->out.tail == connection->out.head) + if (connection->out.tail == connection->out.head && + connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE, connection->data); + connection->write_signalled = 0; + } } if (mask & WL_CONNECTION_READABLE) { @@ -334,11 +338,24 @@ wl_connection_write(struct wl_connection *connection, wl_buffer_put(&connection->out, data, count); - if (connection->out.head - connection->out.tail == count) + if (!connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE | WL_CONNECTION_WRITABLE, connection->data); + connection->write_signalled = 1; + } +} + +static void +wl_connection_queue(struct wl_connection *connection, + const void *data, size_t count) +{ + if (connection->out.head - connection->out.tail + + count > ARRAY_LENGTH(connection->out.data)) + wl_connection_data(connection, WL_CONNECTION_WRITABLE); + + wl_buffer_put(&connection->out, data, count); } static int @@ -703,6 +720,15 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) wl_connection_write(connection, closure->start, size); } +void +wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) +{ + uint32_t size; + + size = closure->start[1] >> 16; + wl_connection_queue(connection, closure->start, size); +} + void wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) { diff --git a/src/connection.h b/src/connection.h index 1c733ff..4f7c928 100644 --- a/src/connection.h +++ b/src/connection.h @@ -61,6 +61,8 @@ wl_closure_invoke(struct wl_closure *closure, void wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); void +wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); +void wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send); void wl_closure_destroy(struct wl_closure *closure); diff --git a/src/wayland-client.c b/src/wayland-client.c index 8f3e106..5845698 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -469,10 +469,6 @@ wl_display_iterate(struct wl_display *display, uint32_t mask) len = wl_connection_data(display->connection, mask); - if (wl_debug && (mask & WL_DISPLAY_READABLE)) - fprintf(stderr, - "[-----------] wakeup, read %d bytes\n", len); - while (len > 0) { if (len < sizeof p) break; diff --git a/src/wayland-server.c b/src/wayland-server.c index 0004c15..f3d8050 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -108,6 +108,28 @@ wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...) wl_closure_destroy(closure); } + +WL_EXPORT void +wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) +{ + struct wl_closure *closure; + struct wl_object *object = &resource->object; + va_list ap; + + va_start(ap, opcode); + closure = wl_connection_vmarshal(resource->client->connection, + object, opcode, ap, + &object->interface->events[opcode]); + va_end(ap); + + wl_closure_queue(closure, resource->client->connection); + + if (wl_debug) + wl_closure_print(closure, object, true); + + wl_closure_destroy(closure); +} + WL_EXPORT void wl_resource_post_error(struct wl_resource *resource, uint32_t code, const char *msg, ...) @@ -314,8 +336,8 @@ wl_resource_destroy(struct wl_resource *resource, uint32_t time) { struct wl_client *client = resource->client; - wl_resource_post_event(resource->client->display_resource, - WL_DISPLAY_DELETE_ID, resource->object.id); + wl_resource_queue_event(resource->client->display_resource, + WL_DISPLAY_DELETE_ID, resource->object.id); wl_map_insert_at(&client->objects, resource->object.id, NULL); destroy_resource(resource, &time); } diff --git a/src/wayland-server.h b/src/wayland-server.h index 9f5e8c3..ead95cc 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -216,6 +216,8 @@ struct wl_selection { void wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...); +void wl_resource_queue_event(struct wl_resource *resource, + uint32_t opcode, ...); void wl_resource_post_error(struct wl_resource *resource, uint32_t code, const char *msg, ...); void wl_resource_post_no_memory(struct wl_resource *resource);