aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenny Levinsen <kl@kl.wtf>2020-08-30 00:05:19 +0200
committerKenny Levinsen <kl@kl.wtf>2020-08-30 00:05:19 +0200
commitc36cc962e6b3fd7bec8093756d4c3a7df9940862 (patch)
tree43afee6a471cc3366be43d434fcf7397baf0180e
parent5470c481134ab194f32f53fd8d5ba7c916478f74 (diff)
linked_list: Implement linked_list_take
-rw-r--r--common/linked_list.c14
-rw-r--r--include/linked_list.h1
-rw-r--r--libseat/backend/seatd.c10
-rw-r--r--tests/linked_list.c44
4 files changed, 61 insertions, 8 deletions
diff --git a/common/linked_list.c b/common/linked_list.c
index cb3e0a8..3d2ee7d 100644
--- a/common/linked_list.c
+++ b/common/linked_list.c
@@ -32,3 +32,17 @@ bool linked_list_empty(struct linked_list *list) {
assert(list->prev != NULL && list->next != NULL);
return list->next == list;
}
+
+void linked_list_take(struct linked_list *target, struct linked_list *source) {
+ if (linked_list_empty(source)) {
+ linked_list_init(target);
+ return;
+ }
+
+ target->next = source->next;
+ target->prev = source->prev;
+ target->next->prev = target;
+ target->prev->next = target;
+
+ linked_list_init(source);
+}
diff --git a/include/linked_list.h b/include/linked_list.h
index 47cf09b..7a20985 100644
--- a/include/linked_list.h
+++ b/include/linked_list.h
@@ -12,5 +12,6 @@ void linked_list_init(struct linked_list *list);
void linked_list_insert(struct linked_list *list, struct linked_list *elem);
void linked_list_remove(struct linked_list *elem);
bool linked_list_empty(struct linked_list *list);
+void linked_list_take(struct linked_list *target, struct linked_list *source);
#endif
diff --git a/libseat/backend/seatd.c b/libseat/backend/seatd.c
index afeab7f..1a187b1 100644
--- a/libseat/backend/seatd.c
+++ b/libseat/backend/seatd.c
@@ -204,14 +204,8 @@ static int queue_event(struct backend_seatd *backend, int opcode) {
}
static void execute_events(struct backend_seatd *backend) {
- struct linked_list list = {
- .next = backend->pending_events.next,
- .prev = backend->pending_events.prev,
- };
- list.next->prev = &list;
- list.prev->next = &list;
-
- linked_list_init(&backend->pending_events);
+ struct linked_list list;
+ linked_list_take(&list, &backend->pending_events);
while (!linked_list_empty(&list)) {
struct pending_event *ev = (struct pending_event *)list.next;
int opcode = ev->opcode;
diff --git a/tests/linked_list.c b/tests/linked_list.c
index a5704a3..a29cff6 100644
--- a/tests/linked_list.c
+++ b/tests/linked_list.c
@@ -201,6 +201,47 @@ static void test_linked_list_loop_iterate(void) {
assert(cnt == 3);
}
+static void test_linked_list_take_empty(void) {
+ struct linked_list list1, list2;
+ linked_list_init(&list1);
+
+ linked_list_take(&list2, &list1);
+
+ assert(linked_list_empty(&list1));
+ assert(linked_list_empty(&list2));
+}
+
+static void test_linked_list_take_single(void) {
+ struct linked_list list1, list2;
+ linked_list_init(&list1);
+
+ struct list_elem elem1 = {{0}, NULL};
+ linked_list_insert(&list1, &elem1.link);
+
+ linked_list_take(&list2, &list1);
+
+ assert(linked_list_empty(&list1));
+ assert(list2.next == &elem1.link && list2.prev == &elem1.link);
+ assert(elem1.link.next == &list2 && elem1.link.prev == &list2);
+}
+
+static void test_linked_list_take_many(void) {
+ struct linked_list list1, list2;
+ linked_list_init(&list1);
+
+ struct list_elem elem1 = {{0}, NULL};
+ struct list_elem elem2 = {{0}, NULL};
+ linked_list_insert(&list1, &elem2.link);
+ linked_list_insert(&list1, &elem1.link);
+
+ linked_list_take(&list2, &list1);
+
+ assert(linked_list_empty(&list1));
+ assert(list2.next == &elem1.link && list2.prev == &elem2.link);
+ assert(elem1.link.next == &elem2.link && elem1.link.prev == &list2);
+ assert(elem2.link.next == &list2 && elem2.link.prev == &elem1.link);
+}
+
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
@@ -214,6 +255,9 @@ int main(int argc, char *argv[]) {
test_linked_list_remove_loop();
test_linked_list_manual_iterate();
test_linked_list_loop_iterate();
+ test_linked_list_take_empty();
+ test_linked_list_take_single();
+ test_linked_list_take_many();
return 0;
}