aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
authorRyan Dwyer <ryandwyer1@gmail.com>2018-08-29 08:29:11 +1000
committerRyan Dwyer <ryandwyer1@gmail.com>2018-08-29 08:29:11 +1000
commitb12f7be9071f085894b47950cc0e1fda2187d7e5 (patch)
treec2d50ea44c1857ec0c0132d9e73f7c32ab7fb91e /sway
parent602ccca1a86a6a8611a287a09feeade17bccfa7c (diff)
Don't use bitfield to test for similar transactions
When there's multiple transactions in the queue, sway can take a shortcut by checking if they all operate on the same set of containers. If they do, it can skip all but the last transaction. The way we tested for transactions which used the same containers was to exclusive-or their con IDs together, but this has proved not only to be ineffective but also has the potential to make sway crash. This patch replaces the exclusive-or with a loop and container comparison.
Diffstat (limited to 'sway')
-rw-r--r--sway/desktop/transaction.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index c18529fb..1316a80d 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -22,7 +22,6 @@ struct sway_transaction {
list_t *instructions; // struct sway_transaction_instruction *
size_t num_waiting;
size_t num_configures;
- uint32_t con_ids; // Bitwise XOR of view container IDs
struct timespec commit_time;
};
@@ -218,6 +217,22 @@ static void transaction_apply(struct sway_transaction *transaction) {
static void transaction_commit(struct sway_transaction *transaction);
+// Return true if both transactions operate on the same containers
+static bool transaction_same_containers(struct sway_transaction *a,
+ struct sway_transaction *b) {
+ if (a->instructions->length != b->instructions->length) {
+ return false;
+ }
+ for (int i = 0; i < a->instructions->length; ++i) {
+ struct sway_transaction_instruction *a_inst = a->instructions->items[i];
+ struct sway_transaction_instruction *b_inst = b->instructions->items[i];
+ if (a_inst->container != b_inst->container) {
+ return false;
+ }
+ }
+ return true;
+}
+
static void transaction_progress_queue() {
if (!server.transactions->length) {
return;
@@ -242,7 +257,7 @@ static void transaction_progress_queue() {
while (server.transactions->length >= 2) {
struct sway_transaction *a = server.transactions->items[0];
struct sway_transaction *b = server.transactions->items[1];
- if (a->con_ids == b->con_ids) {
+ if (transaction_same_containers(a, b)) {
list_del(server.transactions, 0);
transaction_destroy(a);
} else {
@@ -294,7 +309,6 @@ static void transaction_commit(struct sway_transaction *transaction) {
instruction->state.view_width,
instruction->state.view_height);
++transaction->num_waiting;
- transaction->con_ids ^= con->id;
// From here on we are rendering a saved buffer of the view, which
// means we can send a frame done event to make the client redraw it