/* * Copyright (C) 2010 Philippe Gerum . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _BOILERPLATE_SHARED_LIST_H #define _BOILERPLATE_SHARED_LIST_H #ifndef _BOILERPLATE_LIST_H #error "Do not include this file directly. Use instead." #endif #define __hoff(h, a) __memoff(h, a) #define __hptr(h, v) ((struct holder *)__memptr(h, v)) #define __hchk(h, a) __memchk(h, a) struct holder { dref_type(struct holder *) next; dref_type(struct holder *) prev; }; struct listobj { struct holder head; }; static inline void __inith_nocheck(void *heap, struct holder *holder) { holder->next = __hoff(heap, holder); holder->prev = __hoff(heap, holder); } static inline void __inith(void *heap, struct holder *holder) { assert(__hchk(heap, holder)); __inith_nocheck(heap, holder); } static inline void inith(struct holder *holder) { __inith(__main_heap, holder); } static inline void __ath(void *heap, struct holder *head, struct holder *holder) { /* Inserts the new element right after the heading one. */ holder->prev = __hoff(heap, head); holder->next = head->next; __hptr(heap, holder->next)->prev = __hoff(heap, holder); head->next = __hoff(heap, holder); } static inline void ath(struct holder *head, struct holder *holder) { __ath(__main_heap, head, holder); } static inline void __dth(void *heap, struct holder *holder) { __hptr(heap, holder->prev)->next = holder->next; __hptr(heap, holder->next)->prev = holder->prev; } static inline void dth(struct holder *holder) { __dth(__main_heap, holder); } static inline void __list_init(void *heap, struct listobj *list) { __inith(heap, &list->head); } static inline void __list_init_nocheck(void *heap, struct listobj *list) { __inith_nocheck(heap, &list->head); } static inline void list_init(struct listobj *list) { __list_init(__main_heap, list); } static inline void __holder_init(void *heap, struct holder *holder) { __inith(heap, holder); } static inline void __holder_init_nocheck(void *heap, struct holder *holder) { __inith_nocheck(heap, holder); } static inline void holder_init(struct holder *holder) { inith(holder); } static inline int __holder_linked(void *heap, const struct holder *holder) { return !(holder->prev == holder->next && holder->prev == __hoff(heap, holder)); } /* * XXX: holder_init() is mandatory if you later want to use this * predicate. */ static inline int holder_linked(const struct holder *holder) { return __holder_linked(__main_heap, holder); } static inline void __list_prepend(void *heap, struct holder *holder, struct listobj *list) { __ath(heap, &list->head, holder); } static inline void list_prepend(struct holder *holder, struct listobj *list) { __list_prepend(__main_heap, holder, list); } static inline void __list_append(void *heap, struct holder *holder, struct listobj *list) { __ath(heap, __hptr(heap, list->head.prev), holder); } static inline void list_append(struct holder *holder, struct listobj *list) { __list_append(__main_heap, holder, list); } static inline void __list_insert(void *heap, struct holder *next, struct holder *prev) { __ath(heap, prev, next); } static inline void list_insert(struct holder *next, struct holder *prev) { __list_insert(__main_heap, next, prev); } static inline void __list_join(void *heap, struct listobj *lsrc, struct listobj *ldst) { struct holder *headsrc = __hptr(heap, lsrc->head.next); struct holder *tailsrc = __hptr(heap, lsrc->head.prev); struct holder *headdst = &ldst->head; __hptr(heap, headsrc->prev)->next = tailsrc->next; __hptr(heap, tailsrc->next)->prev = headsrc->prev; headsrc->prev = __hoff(heap, headdst); tailsrc->next = headdst->next; __hptr(heap, headdst->next)->prev = __hoff(heap, tailsrc); headdst->next = __hoff(heap, headsrc); } static inline void list_join(struct listobj *lsrc, struct listobj *ldst) { __list_join(__main_heap, lsrc, ldst); } static inline void __list_remove(void *heap, struct holder *holder) { __dth(heap, holder); } static inline void list_remove(struct holder *holder) { __list_remove(__main_heap, holder); } static inline void __list_remove_init(void *heap, struct holder *holder) { __dth(heap, holder); __inith(heap, holder); } static inline void list_remove_init(struct holder *holder) { __list_remove_init(__main_heap, holder); } static inline int __list_empty(void *heap, const struct listobj *list) { return list->head.next == __hoff(heap, &list->head); } static inline int list_empty(const struct listobj *list) { return __list_empty(__main_heap, list); } static inline struct holder *__list_pop(void *heap, struct listobj *list) { struct holder *holder = __hptr(heap, list->head.next); __list_remove(heap, holder); return holder; } static inline struct holder *list_pop(struct listobj *list) { return __list_pop(__main_heap, list); } static inline int __list_heading_p(void *heap, const struct holder *holder, const struct listobj *list) { return list->head.next == __hoff(heap, holder); } static inline int list_heading_p(const struct holder *holder, const struct listobj *list) { return __list_heading_p(__main_heap, holder, list); } #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define __list_first_entry(heap, list, type, member) \ list_entry(__hptr((heap), (list)->head.next), type, member) #define list_first_entry(list, type, member) \ __list_first_entry(__main_heap, list, type, member) #define __list_last_entry(heap, list, type, member) \ list_entry(__hptr((heap), (list)->head.prev), type, member) #define list_last_entry(list, type, member) \ __list_last_entry(__main_heap, list, type, member) #define __list_prev_entry(heap, pos, list, member) \ ({ \ typeof(*pos) *__prev = NULL; \ if ((list)->head.next != __hoff(heap, &(pos)->member)) \ __prev = list_entry(__hptr((heap), \ (pos)->member.prev), typeof(*pos), member); \ __prev; \ }) #define list_prev_entry(pos, list, member) \ __list_prev_entry(__main_heap, pos, list, member) #define __list_next_entry(heap, pos, list, member) \ ({ \ typeof(*pos) *__next = NULL; \ if ((list)->head.prev != __hoff(heap, &(pos)->member)) \ __next = list_entry(__hptr((heap), \ (pos)->member.next), typeof(*pos), member); \ __next; \ }) #define list_next_entry(pos, list, member) \ __list_next_entry(__main_heap, pos, list, member) #define __list_pop_entry(heap, list, type, member) ({ \ struct holder *__holder = __list_pop((heap), list); \ list_entry(__holder, type, member); }) #define list_pop_entry(list, type, member) \ __list_pop_entry(__main_heap, list, type, member) #define __list_for_each(heap, pos, list) \ for (pos = __hptr((heap), (list)->head.next); \ pos != &(list)->head; pos = __hptr((heap), (pos)->next)) #define list_for_each(pos, list) \ __list_for_each(__main_heap, pos, list) #define __list_for_each_reverse(heap, pos, list) \ for (pos = __hptr((heap), (list)->head.prev); \ pos != &(list)->head; pos = __hptr((heap), (pos)->prev)) #define list_for_each_reverse(pos, list) \ __list_for_each_reverse(__main_heap, pos, list) #define __list_for_each_safe(heap, pos, tmp, list) \ for (pos = __hptr((heap), (list)->head.next), \ tmp = __hptr((heap), (pos)->next); \ pos != &(list)->head; \ pos = tmp, tmp = __hptr((heap), (pos)->next)) #define list_for_each_safe(pos, tmp, list) \ __list_for_each_safe(__main_heap, pos, tmp, list) #define __list_for_each_entry(heap, pos, list, member) \ for (pos = list_entry(__hptr((heap), (list)->head.next), \ typeof(*pos), member); \ &(pos)->member != &(list)->head; \ pos = list_entry(__hptr((heap), (pos)->member.next), \ typeof(*pos), member)) #define list_for_each_entry(pos, list, member) \ __list_for_each_entry(__main_heap, pos, list, member) #define __list_for_each_entry_safe(heap, pos, tmp, list, member) \ for (pos = list_entry(__hptr((heap), (list)->head.next), \ typeof(*pos), member), \ tmp = list_entry(__hptr((heap), (pos)->member.next), \ typeof(*pos), member); \ &(pos)->member != &(list)->head; \ pos = tmp, tmp = list_entry(__hptr((heap), (pos)->member.next), \ typeof(*pos), member)) #define __list_for_each_entry_reverse_safe(heap, pos, tmp, list, member) \ for (pos = list_entry(__hptr((heap), (list)->head.prev), \ typeof(*pos), member), \ tmp = list_entry(__hptr((heap), (pos)->member.prev), \ typeof(*pos), member); \ &(pos)->member != &(list)->head; \ pos = tmp, tmp = list_entry(__hptr((heap), (pos)->member.prev), \ typeof(*pos), member)) #define list_for_each_entry_safe(pos, tmp, list, member) \ __list_for_each_entry_safe(__main_heap, pos, tmp, list, member) #define __list_for_each_entry_reverse(heap, pos, list, member) \ for (pos = list_entry(__hptr((heap), (list)->head.prev), \ typeof(*pos), member); \ &pos->member != &(list)->head; \ pos = list_entry(__hptr((heap), pos->member.prev), \ typeof(*pos), member)) #define list_for_each_entry_reverse(pos, list, member) \ __list_for_each_entry_reverse(__main_heap, pos, list, member) #define list_for_each_entry_reverse_safe(pos, tmp, list, member) \ __list_for_each_entry_reverse_safe(__main_heap, pos, tmp, list, member) #endif /* !_BOILERPLATE_SHARED_LIST_H */