nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

commit 3e6fa09993d20cca5b0c2e5b829903f81484413e
parent cba7284221176dbbb2275e479c3eb8a8afc665c6
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  5 Feb 2024 16:47:10 -0800

queue: switch to prot_queue_try_pop_all

This allows you to `try pop` multiple items instead of 1

Diffstat:
Msrc/protected_queue.h | 14++++++++++----
Mtest.c | 10+++++-----
2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/protected_queue.h b/src/protected_queue.h @@ -154,7 +154,9 @@ static int prot_queue_push_all(struct prot_queue* q, void *data, int count) * data - Pointer to where the popped data will be stored. * Returns 1 if successful, 0 if the queue is empty. */ -static inline int prot_queue_try_pop(struct prot_queue *q, void *data) { +static inline int prot_queue_try_pop_all(struct prot_queue *q, void *data, int max_items) { + int items_to_pop, items_until_end; + pthread_mutex_lock(&q->mutex); if (q->count == 0) { @@ -162,9 +164,13 @@ static inline int prot_queue_try_pop(struct prot_queue *q, void *data) { return 0; } - memcpy(data, &q->buf[q->head * q->elem_size], q->elem_size); - q->head = (q->head + 1) % prot_queue_capacity(q); - q->count--; + items_until_end = (q->buflen - q->head * q->elem_size) / q->elem_size; + items_to_pop = min(q->count, max_items); + items_to_pop = min(items_to_pop, items_until_end); + + memcpy(data, &q->buf[q->head * q->elem_size], items_to_pop * q->elem_size); + q->head = (q->head + items_to_pop) % prot_queue_capacity(q); + q->count -= items_to_pop; pthread_mutex_unlock(&q->mutex); return 1; diff --git a/test.c b/test.c @@ -1030,10 +1030,10 @@ static void test_queue_init_pop_push() { // Pop to empty, and then fail to pop for (int i = 0; i < TEST_BUF_SIZE; i++) { - assert(prot_queue_try_pop(&q, &data) == 1); + assert(prot_queue_try_pop_all(&q, &data, 1) == 1); assert(data == i); } - assert(prot_queue_try_pop(&q, &data) == 0); // Should fail as queue is empty + assert(prot_queue_try_pop_all(&q, &data, 1) == 0); // Should fail as queue is empty } // This function will be used by threads to test thread safety. @@ -1068,7 +1068,7 @@ static void test_queue_thread_safety() { // After all operations, the queue should be empty int data; - assert(prot_queue_try_pop(&q, &data) == 0); + assert(prot_queue_try_pop_all(&q, &data, 1) == 0); } static void test_queue_boundary_conditions() { @@ -1097,14 +1097,14 @@ static void test_queue_boundary_conditions() { // Pop to empty for (int i = 0; i < TEST_BUF_SIZE; i++) { - assert(prot_queue_try_pop(&q, &data) == 1); + assert(prot_queue_try_pop_all(&q, &data, 1) == 1); } // Try to pop from an empty queue old_head = q.head; old_tail = q.tail; old_count = q.count; - assert(prot_queue_try_pop(&q, &data) == 0); + assert(prot_queue_try_pop_all(&q, &data, 1) == 0); // Assert the queue's state has not changed assert(old_head == q.head);