#ifndef __IQUEUE_H__ #define __IQUEUE_H__ #include #define IQUEUE_LINK \ struct { \ void *prev; \ void *next; \ } #define IQUEUE(ele_type, link_name) \ struct { \ union { \ struct { \ ele_type *head; \ ele_type *tail; \ unsigned int length; \ }; \ struct { \ char dummy[offsetof(ele_type, link_name)]; \ struct { \ ele_type *prev; \ ele_type *next; \ } link; \ } *offset; \ const ele_type *const_ele; \ }; \ } #define i_queue_init(list) do { \ (list)->head = NULL; \ (list)->tail = NULL; \ (list)->length = 0; \ } while (0) #define IQUEUE_INIT { 0 } #define i_queue_peek_head(list) ({ \ __auto_type __ret = (list)->head; \ __ret; \ }) #define i_queue_pop_head(list) ({ \ __auto_type __ret = (list)->head; \ if (__ret) { \ __auto_type __link = (__typeof((list)->offset)) __ret; \ (list)->head = __link->link.next; \ __link->link.next = NULL; \ (list)->length--; \ if (!(list)->head) \ (list)->tail = NULL; \ } \ __ret; \ }) #define i_queue_push_tail(list, ele) do { \ if ((list)->tail) { \ __auto_type __link = (__typeof((list)->offset)) (list)->tail; \ __link->link.next = ele; \ } \ __auto_type __link = (__typeof((list)->offset)) ele; \ __link->link.prev = (list)->tail; \ (list)->tail = ele; \ if (!(list)->head) \ (list)->head = ele; \ (list)->length++; \ } while (0) #define i_queue_push_head(list, ele) do { \ if ((list)->head) { \ __auto_type __link = (__typeof((list)->offset)) (list)->head; \ __link->link.prev = ele; \ } \ __auto_type __link = (__typeof((list)->offset)) ele; \ __link->link.next = (list)->head; \ (list)->head = ele; \ if (!(list)->tail) \ (list)->tail = ele; \ (list)->length++; \ } while (0) #define i_queue_delete(list, ele) do { \ __auto_type __link = (__typeof((list)->offset)) ele; \ if (__link->link.next) { \ __auto_type __next_link = (__typeof((list)->offset)) __link->link.next; \ __next_link->link.prev = __link->link.prev; \ } \ else \ (list)->tail = __link->link.prev; \ if (__link->link.prev) { \ __auto_type __prev_link = (__typeof((list)->offset)) __link->link.prev; \ __prev_link->link.next = __link->link.next; \ } \ else \ (list)->head = __link->link.next; \ } while (0) #define IQUEUE_FOREACH(list, var) \ for (__typeof__ ( ({ __typeof__ (*(list)->head) __t; &__t; }) ) var = (list)->head; \ var; var = ((__typeof((list)->offset)) var)->link.next) #define IQUEUE_FOREACH_SAFE(list, var) \ for (__typeof__ ( ({ __typeof__ (*(list)->head) __t; &__t; }) ) var = (list)->head, \ __next ## var = var ? ((__typeof((list)->offset)) var)->link.next : NULL; \ var; \ var = __next ## var, \ __next ## var = var ? ((__typeof((list)->offset)) var)->link.next : NULL) #define i_queue_clear_full(list, fn) do { \ IQUEUE_FOREACH_SAFE(list, __ele) \ (fn)(__ele); \ i_queue_init(list); \ } while (0) #define i_queue_find(list, fn) ({ \ __typeof__ ((list)->head) __ret = NULL; \ bool (*__fn)(__typeof__ ((list)->const_ele)) = (fn); \ IQUEUE_FOREACH(list, __ele) { \ if (__fn(__ele)) { \ __ret = __ele; \ break; \ } \ } \ __ret; \ }) #endif