summaryrefslogtreecommitdiff
path: root/drivers/staging/csr/oska/list.h
blob: a69b3b7d96b4396d239150b691ef683f9c6d7d1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * Operating system kernel abstraction -- linked lists.
 *
 * Copyright (C) 2009-2010 Cambridge Silicon Radio Ltd.
 *
 * Refer to LICENSE.txt included with this source code for details on
 * the license terms.
 */
#ifndef __OSKA_LIST_H
#define __OSKA_LIST_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @defgroup list Linked Lists
 *
 * Generic linked list implementations suitable for all platforms.
 *
 *   - Circular, doubly-linked list (struct os_list).
 */

/**
 * A list node.
 *
 * This list node structure should be the first field within any
 * structure that is to be stored in a list.
 *
 * @see struct os_list
 * @ingroup list
 */
struct os_list_node {
    /**
     * The pointer to the previous node in the list, or os_list_end()
     * if the end of the list has been reached.
     */
    struct os_list_node *prev;
    /**
     * The pointer to the next node in the list, or os_list_end() if
     * the end of the list has been reached.
     */
    struct os_list_node *next;
};

/**
 * A circular, doubly-linked list of nodes.
 *
 * Structures to be stored in a list should contains a struct
 * os_list_node as the \e first field.
 * \code
 *   struct foo {
 *      struct os_list_node node;
 *      int bar;
 *      ...
 *   };
 * \endcode
 * Going to/from a struct foo to a list node is then simple.
 * \code
 *   struct os_list_node *node;
 *   struct foo *foo;
 *   [...]
 *   node = &foo->node;
 *   foo = (struct foo *)node
 * \endcode
 * Lists must be initialized with os_list_init() before adding nodes
 * with os_list_add_tail().  The node at the head of the list is
 * obtained with os_list_head().  Nodes are removed from the list with
 * os_list_del().
 *
 * A list can be interated from the head to the tail using:
 * \code
 *   struct os_list_node *node;
 *   for (node = os_list_head(list); node != os_list_end(list); node = node->next) {
 *      struct foo *foo = (struct foo *)node;
 *      ...
 *   }
 * \endcode
 *
 * In the above loop, the current list node cannot be removed (with
 * os_list_del()).  If this is required use this form of loop:
 * \code
 *   struct os_list_node *node, *next;
 *   for (node = os_list_head(list), next = node->next;
 *        node != os_list_end(list);
 *        node = next, next = node->next) {
 *      struct foo *foo = (struct foo *)node;
 *      ...
 *      os_list_del(node);
 *      ...
 *   }
 * \endcode
 *
 * @ingroup list
 */
struct os_list {
    /**
     * @internal
     * The dummy node marking the end of the list.
     */
    struct os_list_node head;
};

void os_list_init(struct os_list *list);
int os_list_empty(struct os_list *list);
void os_list_add_tail(struct os_list *list, struct os_list_node *node);
void os_list_del(struct os_list_node *node);
struct os_list_node *os_list_head(struct os_list *list);
struct os_list_node *os_list_end(struct os_list *list);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* #ifndef __OSKA_LIST_H */