Allow views to skip configures

To do this properly, the transaction queue will only be processed if it
can be completely processed.
This commit is contained in:
Ryan Dwyer 2018-06-27 19:07:48 +10:00
parent e6829c5991
commit 9652529cc1
5 changed files with 42 additions and 22 deletions

View file

@ -62,6 +62,13 @@ void list_cat(list_t *list, list_t *source) {
} }
} }
void list_empty(list_t *list) {
list->capacity = 10;
list->length = 0;
free(list->items);
list->items = malloc(sizeof(void*) * list->capacity);
}
void list_qsort(list_t *list, int compare(const void *left, const void *right)) { void list_qsort(list_t *list, int compare(const void *left, const void *right)) {
qsort(list->items, list->length, sizeof(void *), compare); qsort(list->items, list->length, sizeof(void *), compare);
} }

View file

@ -14,6 +14,7 @@ void list_add(list_t *list, void *item);
void list_insert(list_t *list, int index, void *item); void list_insert(list_t *list, int index, void *item);
void list_del(list_t *list, int index); void list_del(list_t *list, int index);
void list_cat(list_t *list, list_t *source); void list_cat(list_t *list, list_t *source);
void list_empty(list_t *list);
// See qsort. Remember to use *_qsort functions as compare functions, // See qsort. Remember to use *_qsort functions as compare functions,
// because they dereference the left and right arguments first! // because they dereference the left and right arguments first!
void list_qsort(list_t *list, int compare(const void *left, const void *right)); void list_qsort(list_t *list, int compare(const void *left, const void *right));

View file

@ -47,7 +47,7 @@ struct sway_server {
bool debug_txn_timings; bool debug_txn_timings;
struct sway_transaction *head_transaction; // singly linked list list_t *transactions;
// When a view is being destroyed and is waiting for a transaction to // When a view is being destroyed and is waiting for a transaction to
// complete it will be stored here. // complete it will be stored here.

View file

@ -32,7 +32,6 @@ struct sway_transaction {
list_t *instructions; // struct sway_transaction_instruction * list_t *instructions; // struct sway_transaction_instruction *
size_t num_waiting; size_t num_waiting;
size_t num_configures; size_t num_configures;
struct sway_transaction *next;
struct timespec create_time; struct timespec create_time;
struct timespec commit_time; struct timespec commit_time;
}; };
@ -225,16 +224,24 @@ static void transaction_apply(struct sway_transaction *transaction) {
} }
} }
/**
* For simplicity, we only progress the queue if it can be completely flushed.
*/
static void transaction_progress_queue() { static void transaction_progress_queue() {
struct sway_transaction *transaction = server.head_transaction; // We iterate this list in reverse because we're more likely to find a
struct sway_transaction *next = NULL; // waiting transactions at the end of the list.
while (transaction && !transaction->num_waiting) { for (int i = server.transactions->length - 1; i >= 0; --i) {
next = transaction->next; struct sway_transaction *transaction = server.transactions->items[i];
if (transaction->num_waiting) {
return;
}
}
for (int i = 0; i < server.transactions->length; ++i) {
struct sway_transaction *transaction = server.transactions->items[i];
transaction_apply(transaction); transaction_apply(transaction);
transaction_destroy(transaction); transaction_destroy(transaction);
transaction = next;
} }
server.head_transaction = transaction; list_empty(server.transactions);
} }
static int handle_timeout(void *data) { static int handle_timeout(void *data) {
@ -295,18 +302,8 @@ void transaction_commit(struct sway_transaction *transaction) {
if (server.debug_txn_timings) { if (server.debug_txn_timings) {
clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time); clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time);
} }
if (server.head_transaction) { if (server.transactions->length || transaction->num_waiting) {
// There is another transaction in progress - we must add this one to list_add(server.transactions, transaction);
// the queue so we complete after it.
struct sway_transaction *tail = server.head_transaction;
while (tail->next) {
tail = tail->next;
}
tail->next = transaction;
} else if (transaction->num_waiting) {
// There are no other transactions, but we're not applying immediately
// so we must jump in the queue so others will queue behind us.
server.head_transaction = transaction;
} else { } else {
// There are no other transactions in progress, and this one has nothing // There are no other transactions in progress, and this one has nothing
// to wait for, so we can skip the queue. // to wait for, so we can skip the queue.
@ -359,12 +356,24 @@ static void set_instruction_ready(
} }
} }
/**
* Mark all of the view's instructions as ready up to and including the
* instruction at the given index. This allows the view to skip a configure.
*/
static void set_instructions_ready(struct sway_view *view, int index) {
for (int i = 0; i <= index; ++i) {
struct sway_transaction_instruction *instruction =
view->swayc->instructions->items[i];
set_instruction_ready(instruction);
}
}
void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) {
for (int i = 0; i < view->swayc->instructions->length; ++i) { for (int i = 0; i < view->swayc->instructions->length; ++i) {
struct sway_transaction_instruction *instruction = struct sway_transaction_instruction *instruction =
view->swayc->instructions->items[i]; view->swayc->instructions->items[i];
if (instruction->serial == serial && !instruction->ready) { if (instruction->serial == serial && !instruction->ready) {
set_instruction_ready(instruction); set_instructions_ready(view, i);
return; return;
} }
} }
@ -377,7 +386,7 @@ void transaction_notify_view_ready_by_size(struct sway_view *view,
view->swayc->instructions->items[i]; view->swayc->instructions->items[i];
if (!instruction->ready && instruction->state.view_width == width && if (!instruction->ready && instruction->state.view_width == width &&
instruction->state.view_height == height) { instruction->state.view_height == height) {
set_instruction_ready(instruction); set_instructions_ready(view, i);
return; return;
} }
} }

View file

@ -119,6 +119,8 @@ bool server_init(struct sway_server *server) {
} }
server->destroying_containers = create_list(); server->destroying_containers = create_list();
server->transactions = create_list();
input_manager = input_manager_create(server); input_manager = input_manager_create(server);
return true; return true;
} }
@ -127,6 +129,7 @@ void server_fini(struct sway_server *server) {
// TODO: free sway-specific resources // TODO: free sway-specific resources
wl_display_destroy(server->wl_display); wl_display_destroy(server->wl_display);
list_free(server->destroying_containers); list_free(server->destroying_containers);
list_free(server->transactions);
} }
void server_run(struct sway_server *server) { void server_run(struct sway_server *server) {