diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-27 19:07:48 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-27 19:07:48 +1000 |
commit | 9652529cc161e943241d946dac93ab16d5e30ee5 (patch) | |
tree | ad1b0c728dd970449e7033f3b3eda4b549bd3fab | |
parent | Move unsetting of view->surface into view_unmap (diff) | |
download | sway-9652529cc161e943241d946dac93ab16d5e30ee5.tar.gz sway-9652529cc161e943241d946dac93ab16d5e30ee5.tar.zst sway-9652529cc161e943241d946dac93ab16d5e30ee5.zip |
Allow views to skip configures
To do this properly, the transaction queue will only be processed if it
can be completely processed.
-rw-r--r-- | common/list.c | 7 | ||||
-rw-r--r-- | include/list.h | 1 | ||||
-rw-r--r-- | include/sway/server.h | 2 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 51 | ||||
-rw-r--r-- | sway/server.c | 3 |
5 files changed, 42 insertions, 22 deletions
diff --git a/common/list.c b/common/list.c index 39cc10e1..cab10c1e 100644 --- a/common/list.c +++ b/common/list.c | |||
@@ -62,6 +62,13 @@ void list_cat(list_t *list, list_t *source) { | |||
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | void list_empty(list_t *list) { | ||
66 | list->capacity = 10; | ||
67 | list->length = 0; | ||
68 | free(list->items); | ||
69 | list->items = malloc(sizeof(void*) * list->capacity); | ||
70 | } | ||
71 | |||
65 | void list_qsort(list_t *list, int compare(const void *left, const void *right)) { | 72 | void list_qsort(list_t *list, int compare(const void *left, const void *right)) { |
66 | qsort(list->items, list->length, sizeof(void *), compare); | 73 | qsort(list->items, list->length, sizeof(void *), compare); |
67 | } | 74 | } |
diff --git a/include/list.h b/include/list.h index 7eead4ac..d352dbd5 100644 --- a/include/list.h +++ b/include/list.h | |||
@@ -14,6 +14,7 @@ void list_add(list_t *list, void *item); | |||
14 | void list_insert(list_t *list, int index, void *item); | 14 | void list_insert(list_t *list, int index, void *item); |
15 | void list_del(list_t *list, int index); | 15 | void list_del(list_t *list, int index); |
16 | void list_cat(list_t *list, list_t *source); | 16 | void list_cat(list_t *list, list_t *source); |
17 | void list_empty(list_t *list); | ||
17 | // See qsort. Remember to use *_qsort functions as compare functions, | 18 | // See qsort. Remember to use *_qsort functions as compare functions, |
18 | // because they dereference the left and right arguments first! | 19 | // because they dereference the left and right arguments first! |
19 | void list_qsort(list_t *list, int compare(const void *left, const void *right)); | 20 | void list_qsort(list_t *list, int compare(const void *left, const void *right)); |
diff --git a/include/sway/server.h b/include/sway/server.h index bd96b085..0efc6baa 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -47,7 +47,7 @@ struct sway_server { | |||
47 | 47 | ||
48 | bool debug_txn_timings; | 48 | bool debug_txn_timings; |
49 | 49 | ||
50 | struct sway_transaction *head_transaction; // singly linked list | 50 | list_t *transactions; |
51 | 51 | ||
52 | // When a view is being destroyed and is waiting for a transaction to | 52 | // When a view is being destroyed and is waiting for a transaction to |
53 | // complete it will be stored here. | 53 | // complete it will be stored here. |
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index c29b6661..7a2e78e5 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -32,7 +32,6 @@ struct sway_transaction { | |||
32 | list_t *instructions; // struct sway_transaction_instruction * | 32 | list_t *instructions; // struct sway_transaction_instruction * |
33 | size_t num_waiting; | 33 | size_t num_waiting; |
34 | size_t num_configures; | 34 | size_t num_configures; |
35 | struct sway_transaction *next; | ||
36 | struct timespec create_time; | 35 | struct timespec create_time; |
37 | struct timespec commit_time; | 36 | struct timespec commit_time; |
38 | }; | 37 | }; |
@@ -225,16 +224,24 @@ static void transaction_apply(struct sway_transaction *transaction) { | |||
225 | } | 224 | } |
226 | } | 225 | } |
227 | 226 | ||
227 | /** | ||
228 | * For simplicity, we only progress the queue if it can be completely flushed. | ||
229 | */ | ||
228 | static void transaction_progress_queue() { | 230 | static void transaction_progress_queue() { |
229 | struct sway_transaction *transaction = server.head_transaction; | 231 | // We iterate this list in reverse because we're more likely to find a |
230 | struct sway_transaction *next = NULL; | 232 | // waiting transactions at the end of the list. |
231 | while (transaction && !transaction->num_waiting) { | 233 | for (int i = server.transactions->length - 1; i >= 0; --i) { |
232 | next = transaction->next; | 234 | struct sway_transaction *transaction = server.transactions->items[i]; |
235 | if (transaction->num_waiting) { | ||
236 | return; | ||
237 | } | ||
238 | } | ||
239 | for (int i = 0; i < server.transactions->length; ++i) { | ||
240 | struct sway_transaction *transaction = server.transactions->items[i]; | ||
233 | transaction_apply(transaction); | 241 | transaction_apply(transaction); |
234 | transaction_destroy(transaction); | 242 | transaction_destroy(transaction); |
235 | transaction = next; | ||
236 | } | 243 | } |
237 | server.head_transaction = transaction; | 244 | list_empty(server.transactions); |
238 | } | 245 | } |
239 | 246 | ||
240 | static int handle_timeout(void *data) { | 247 | static int handle_timeout(void *data) { |
@@ -295,18 +302,8 @@ void transaction_commit(struct sway_transaction *transaction) { | |||
295 | if (server.debug_txn_timings) { | 302 | if (server.debug_txn_timings) { |
296 | clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time); | 303 | clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time); |
297 | } | 304 | } |
298 | if (server.head_transaction) { | 305 | if (server.transactions->length || transaction->num_waiting) { |
299 | // There is another transaction in progress - we must add this one to | 306 | list_add(server.transactions, transaction); |
300 | // the queue so we complete after it. | ||
301 | struct sway_transaction *tail = server.head_transaction; | ||
302 | while (tail->next) { | ||
303 | tail = tail->next; | ||
304 | } | ||
305 | tail->next = transaction; | ||
306 | } else if (transaction->num_waiting) { | ||
307 | // There are no other transactions, but we're not applying immediately | ||
308 | // so we must jump in the queue so others will queue behind us. | ||
309 | server.head_transaction = transaction; | ||
310 | } else { | 307 | } else { |
311 | // There are no other transactions in progress, and this one has nothing | 308 | // There are no other transactions in progress, and this one has nothing |
312 | // to wait for, so we can skip the queue. | 309 | // to wait for, so we can skip the queue. |
@@ -359,12 +356,24 @@ static void set_instruction_ready( | |||
359 | } | 356 | } |
360 | } | 357 | } |
361 | 358 | ||
359 | /** | ||
360 | * Mark all of the view's instructions as ready up to and including the | ||
361 | * instruction at the given index. This allows the view to skip a configure. | ||
362 | */ | ||
363 | static void set_instructions_ready(struct sway_view *view, int index) { | ||
364 | for (int i = 0; i <= index; ++i) { | ||
365 | struct sway_transaction_instruction *instruction = | ||
366 | view->swayc->instructions->items[i]; | ||
367 | set_instruction_ready(instruction); | ||
368 | } | ||
369 | } | ||
370 | |||
362 | void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { | 371 | void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { |
363 | for (int i = 0; i < view->swayc->instructions->length; ++i) { | 372 | for (int i = 0; i < view->swayc->instructions->length; ++i) { |
364 | struct sway_transaction_instruction *instruction = | 373 | struct sway_transaction_instruction *instruction = |
365 | view->swayc->instructions->items[i]; | 374 | view->swayc->instructions->items[i]; |
366 | if (instruction->serial == serial && !instruction->ready) { | 375 | if (instruction->serial == serial && !instruction->ready) { |
367 | set_instruction_ready(instruction); | 376 | set_instructions_ready(view, i); |
368 | return; | 377 | return; |
369 | } | 378 | } |
370 | } | 379 | } |
@@ -377,7 +386,7 @@ void transaction_notify_view_ready_by_size(struct sway_view *view, | |||
377 | view->swayc->instructions->items[i]; | 386 | view->swayc->instructions->items[i]; |
378 | if (!instruction->ready && instruction->state.view_width == width && | 387 | if (!instruction->ready && instruction->state.view_width == width && |
379 | instruction->state.view_height == height) { | 388 | instruction->state.view_height == height) { |
380 | set_instruction_ready(instruction); | 389 | set_instructions_ready(view, i); |
381 | return; | 390 | return; |
382 | } | 391 | } |
383 | } | 392 | } |
diff --git a/sway/server.c b/sway/server.c index a2bc5702..884d971e 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -119,6 +119,8 @@ bool server_init(struct sway_server *server) { | |||
119 | } | 119 | } |
120 | server->destroying_containers = create_list(); | 120 | server->destroying_containers = create_list(); |
121 | 121 | ||
122 | server->transactions = create_list(); | ||
123 | |||
122 | input_manager = input_manager_create(server); | 124 | input_manager = input_manager_create(server); |
123 | return true; | 125 | return true; |
124 | } | 126 | } |
@@ -127,6 +129,7 @@ void server_fini(struct sway_server *server) { | |||
127 | // TODO: free sway-specific resources | 129 | // TODO: free sway-specific resources |
128 | wl_display_destroy(server->wl_display); | 130 | wl_display_destroy(server->wl_display); |
129 | list_free(server->destroying_containers); | 131 | list_free(server->destroying_containers); |
132 | list_free(server->transactions); | ||
130 | } | 133 | } |
131 | 134 | ||
132 | void server_run(struct sway_server *server) { | 135 | void server_run(struct sway_server *server) { |