1/*
2 * Copyright 2003-2007, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef KERNEL_LIST_H
6#define KERNEL_LIST_H
7
8
9#include <SupportDefs.h>
10
11
12/* This header defines a doubly-linked list. It differentiates between a link
13 * and an item.
14 * A link is what is put into and removed from a list, an item is the whole
15 * object that contains the link. The item doesn't have to be begin with a
16 * link; the offset to the link structure is given to init_list_etc(), so that
17 * list_get_next/prev_item() will work correctly.
18 * Note, the offset value is only needed for the *_item() functions. If the
19 * offset is 0, list_link and item are identical - if you use init_list(),
20 * you don't have to care about the difference between a link and an item.
21 */
22
23
24// The use of offsetof() on non-PODs is invalid. Since many structs use
25// templated members (i.e. DoublyLinkedList) which makes them non-PODs we
26// can't use offsetof() anymore. This macro does the same, but requires an
27// instance of the object in question.
28#define offset_of_member(OBJECT, MEMBER) \
29	((size_t)((char*)&OBJECT.MEMBER - (char*)&OBJECT))
30
31
32typedef struct list_link list_link;
33
34/* The object that is put into the list must begin with these
35 * fields, but it doesn't have to be this structure.
36 */
37
38struct list_link {
39	list_link	*next;
40	list_link	*prev;
41};
42
43struct list {
44	list_link	link;
45	int32		offset;
46};
47
48
49#ifdef __cplusplus
50extern "C" {
51#endif
52
53extern void list_init(struct list *list);
54extern void list_init_etc(struct list *list, int32 offset);
55extern void list_add_link_to_head(struct list *list, void *_link);
56extern void list_add_link_to_tail(struct list *list, void *_link);
57extern void list_remove_link(void *_link);
58extern void *list_get_next_item(struct list *list, void *item);
59extern void *list_get_prev_item(struct list *list, void *item);
60extern void *list_get_last_item(struct list *list);
61extern void list_add_item(struct list *list, void *item);
62extern void list_remove_item(struct list *list, void *item);
63extern void list_insert_item_before(struct list *list, void *before, void *item);
64extern void *list_remove_head_item(struct list *list);
65extern void *list_remove_tail_item(struct list *list);
66extern void list_move_to_list(struct list *sourceList, struct list *targetList);
67
68static inline bool
69list_is_empty(struct list *list)
70{
71	return list->link.next == (list_link *)list;
72}
73
74static inline void *
75list_get_first_item(struct list *list)
76{
77	return list_get_next_item(list, NULL);
78}
79
80#ifdef __cplusplus
81}
82#endif
83
84#endif	/* KERNEL_LIST_H */
85