diff options
Diffstat (limited to 'source/object.c')
| -rw-r--r-- | source/object.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/source/object.c b/source/object.c new file mode 100644 index 0000000..d569df0 --- /dev/null +++ b/source/object.c @@ -0,0 +1,34 @@ + +#include "kpl.h" + +extern inline void kpl_object_queue_init(kpl_object_queue *object_queue); + +extern inline void kpl_object_queue_enqueue(kpl_object_queue *object_queue, void *object); + +void *kpl_object_queue_dequeue(kpl_object_queue *object_queue) { + kpl_object *object = NULL; + for (;;) { + kpl_object *tail = object_queue->tail, *queue_next = __atomic_load_n(&tail->queue_next, __ATOMIC_ACQUIRE); + if (tail == (kpl_object*) &object_queue->dummy) { + if (!queue_next) + break; + tail = object_queue->tail = queue_next; + queue_next = __atomic_load_n(&tail->queue_next, __ATOMIC_ACQUIRE); + } + if (!queue_next) { + kpl_object *head = __atomic_load_n(&object_queue->head, __ATOMIC_ACQUIRE); + if (head != tail) + continue; + kpl_object_queue_enqueue(object_queue, (kpl_object*) &object_queue->dummy); + queue_next = __atomic_load_n(&tail->queue_next, __ATOMIC_ACQUIRE); + } + if (queue_next) { + object_queue->tail = queue_next; + object = tail; + break; + } + } + if (object) + __atomic_store_n(&object->queue_next, NULL, __ATOMIC_RELAXED); + return object; +} |
