#ifndef UCS_QUEUE_H_
#define UCS_QUEUE_H_
#include "queue_types.h"
#include <ucs/debug/assert.h>
#include <stddef.h>
static inline void ucs_queue_head_init(ucs_queue_head_t *queue)
{
#ifdef __clang_analyzer__
queue->head = (ucs_queue_elem_t*)(void*)queue;
#endif
queue->ptail = &queue->head;
}
static inline size_t ucs_queue_length(ucs_queue_head_t *queue)
{
ucs_queue_elem_t **pelem;
size_t length;
length = 0;
for (pelem = &queue->head; pelem != queue->ptail; pelem = &(*pelem)->next) {
++length;
}
return length;
}
static inline int
ucs_queue_is_tail(ucs_queue_head_t *queue, ucs_queue_elem_t *elem)
{
return queue->ptail == &elem->next;
}
static inline int ucs_queue_is_empty(ucs_queue_head_t *queue)
{
return queue->ptail == &queue->head;
}
static inline void ucs_queue_push(ucs_queue_head_t *queue, ucs_queue_elem_t *elem)
{
*queue->ptail = elem;
queue->ptail = &elem->next;
#if UCS_ENABLE_ASSERT
elem->next = NULL;
#endif
}
static inline void ucs_queue_push_head(ucs_queue_head_t *queue,
ucs_queue_elem_t *elem)
{
elem->next = queue->head;
queue->head = elem;
if (ucs_queue_is_empty(queue)) {
queue->ptail = &elem->next;
}
}
static inline ucs_queue_elem_t *ucs_queue_pull_non_empty(ucs_queue_head_t *queue)
{
ucs_queue_elem_t *elem;
elem = queue->head;
queue->head = elem->next;
if (ucs_queue_is_tail(queue, elem)) {
queue->ptail = &queue->head;
}
return elem;
}
static inline void ucs_queue_del_iter(ucs_queue_head_t *queue, ucs_queue_iter_t iter)
{
ucs_assert((iter != NULL) && (*iter != NULL));
if (ucs_queue_is_tail(queue, *iter)) {
queue->ptail = iter;
*iter = NULL;
} else {
*iter = (*iter)->next;
}
ucs_assertv((queue->head != NULL) || ucs_queue_is_empty(queue),
"head=%p ptail=%p &head=%p iter=%p", queue->head, queue->ptail,
&queue->head, iter);
ucs_assertv(!ucs_queue_is_empty(queue) || (queue->head == NULL),
"head=%p ptail=%p &head=%p iter=%p", queue->head, queue->ptail,
&queue->head, iter);
}
static inline ucs_queue_elem_t *ucs_queue_pull(ucs_queue_head_t *queue)
{
if (ucs_queue_is_empty(queue))
return NULL;
return ucs_queue_pull_non_empty(queue);
}
static inline void ucs_queue_splice(ucs_queue_head_t *queue,
ucs_queue_head_t *new_elems)
{
if (!ucs_queue_is_empty(new_elems)) {
*queue->ptail = new_elems->head;
queue->ptail = new_elems->ptail;
new_elems->ptail = &new_elems->head;
}
}
#define ucs_queue_pull_elem_non_empty(queue, type, member) \
ucs_container_of(ucs_queue_pull_non_empty(queue), type, member)
#define ucs_queue_head_elem_non_empty(queue, type, member) \
ucs_container_of((queue)->head, type, member)
#define ucs_queue_tail_elem_non_empty(queue, type, member) \
ucs_container_of((queue)->ptail, type, member)
#define ucs_queue_for_each(elem, queue, member) \
\
for (*(queue)->ptail = (ucs_queue_elem_t*)(void*)(queue), \
elem = ucs_container_of((queue)->head, ucs_typeof(*elem), member); \
(UCS_PTR_BYTE_OFFSET(elem, ucs_offsetof(ucs_typeof(*elem), member)) != \
(void*)(queue)); \
elem = ucs_container_of(elem->member.next, ucs_typeof(*elem), member))
#define ucs_queue_for_each_safe(elem, iter, queue, member) \
for (iter = &(queue)->head, \
elem = ucs_container_of(*iter, ucs_typeof(*elem), member); \
iter != (queue)->ptail; \
iter = (*iter == &elem->member) ? &(*iter)->next : iter, \
elem = ucs_container_of(*iter, ucs_typeof(*elem), member))
#define ucs_queue_for_each_extract(elem, queue, member, cond) \
for (elem = ucs_container_of((queue)->head, ucs_typeof(*elem), member); \
\
!ucs_queue_is_empty(queue) && (cond) && ucs_queue_pull_non_empty(queue); \
\
elem = ucs_container_of((queue)->head, ucs_typeof(*elem), member))
static inline ucs_queue_iter_t ucs_queue_iter_begin(ucs_queue_head_t *q)
{
return &q->head;
}
static inline ucs_queue_iter_t ucs_queue_iter_next(ucs_queue_iter_t i)
{
return &(*i)->next;
}
static inline int ucs_queue_iter_end(ucs_queue_head_t *q, ucs_queue_iter_t i)
{
return i == q->ptail;
}
static inline void ucs_queue_remove(ucs_queue_head_t *queue, ucs_queue_elem_t *elem)
{
ucs_queue_iter_t iter = ucs_queue_iter_begin(queue);
while (!ucs_queue_iter_end(queue, iter)) {
if (*iter == elem) {
ucs_queue_del_iter(queue, iter);
return;
}
iter = ucs_queue_iter_next(iter);
}
}
#define ucs_queue_iter_elem(elem, iter, member) \
ucs_container_of(*iter, typeof(*elem), member)
#endif