/
list.h
170 lines (144 loc) · 5.58 KB
/
list.h
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
Copyright (C) 2010, Parrot Foundation.
=head1 NAME
src/gc/list.h - Linked lists of allocated objects.
=head1 DESCRIPTION
Implementation of double linked lists used by various GC implementations.
*/
#ifndef PARROT_GC_LIST_H_GUARD
#define PARROT_GC_LIST_H_GUARD
/* Allocatable objects has headers to use in linked lists */
typedef struct List_Item_Header {
struct List_Item_Header *prev;
struct List_Item_Header *next;
#ifndef NDEBUG
struct Linked_List *owner;
#endif
} List_Item_Header;
/* Double-linked list. */
/* N.B. List doesn't _own_ items */
typedef struct Linked_List {
struct List_Item_Header *first;
struct List_Item_Header *last;
/* Cache object count in list. We use it very often */
size_t count;
} Linked_List;
/* Such headers allocated in front of real objects. */
/* There is helper macros to convert to/from real objects */
#define Obj2LLH(p) ((List_Item_Header *)((char*)(p) - sizeof (List_Item_Header)))
#define LLH2Obj_typed(p, type) ((type*)((char*)(p) + sizeof (List_Item_Header)))
#define LLH2Obj(p) LLH2Obj_typed(p, void)
#ifdef NDEBUG
# define SET_LIST_OWNER(l, i)
#else
# define SET_LIST_OWNER(l, i) (i)->owner = (l);
#endif
#define LIST_APPEND(l, i) \
do { \
List_Item_Header *_item = (i); \
Linked_List *_list = (l); \
\
if (_list->last) { \
_item->prev = _list->last; \
_list->last->next = _item; \
} \
else if (!_list->first) { \
_item->prev = NULL; \
_list->first = _item; \
} \
\
_list->last = _item; \
_item->next = NULL; \
\
SET_LIST_OWNER(_list, _item) \
_list->count++; \
} while (0);
#define LIST_REMOVE(l, i) \
do { \
List_Item_Header *_item = (i); \
Linked_List *_list = (l); \
List_Item_Header *next = _item->next; \
List_Item_Header *prev = _item->prev; \
\
PARROT_ASSERT(_list == _item->owner); \
\
/* First _item */ \
if (_list->first == _item) \
_list->first = next; \
\
if (_list->last == _item) \
_list->last = prev; \
\
if (prev) \
prev->next = next; \
if (next) \
next->prev = prev; \
\
_list->count--; \
} while (0)
/* HEADERIZER BEGIN: src/list.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
PARROT_EXPORT
void Parrot_list_append(PARROT_INTERP,
ARGMOD(Linked_List *list),
ARGMOD(List_Item_Header *item))
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*list)
FUNC_MODIFIES(*item);
PARROT_EXPORT
PARROT_CONST_FUNCTION
INTVAL Parrot_list_check(PARROT_INTERP, ARGIN(const Linked_List *list))
__attribute__nonnull__(2);
PARROT_EXPORT
PARROT_PURE_FUNCTION
INTVAL Parrot_list_contains(PARROT_INTERP,
ARGIN(const Linked_List *list),
ARGIN(const List_Item_Header *item))
__attribute__nonnull__(2)
__attribute__nonnull__(3);
PARROT_EXPORT
void Parrot_list_destroy(PARROT_INTERP, ARGMOD(Linked_List* list))
__attribute__nonnull__(2)
FUNC_MODIFIES(* list);
PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
struct Linked_List* Parrot_list_new(PARROT_INTERP);
PARROT_EXPORT
PARROT_CAN_RETURN_NULL
List_Item_Header* Parrot_list_pop(PARROT_INTERP, ARGIN(Linked_List *list))
__attribute__nonnull__(2);
PARROT_EXPORT
PARROT_CAN_RETURN_NULL
List_Item_Header* Parrot_list_remove(PARROT_INTERP,
ARGMOD(Linked_List *list),
ARGMOD(List_Item_Header *item))
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*list)
FUNC_MODIFIES(*item);
#define ASSERT_ARGS_Parrot_list_append __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list) \
, PARROT_ASSERT_ARG(item))
#define ASSERT_ARGS_Parrot_list_check __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list))
#define ASSERT_ARGS_Parrot_list_contains __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list) \
, PARROT_ASSERT_ARG(item))
#define ASSERT_ARGS_Parrot_list_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list))
#define ASSERT_ARGS_Parrot_list_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
#define ASSERT_ARGS_Parrot_list_pop __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list))
#define ASSERT_ARGS_Parrot_list_remove __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(list) \
, PARROT_ASSERT_ARG(item))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: src/list.c */
#endif /* PARROT_GC_LIST_H_GUARD */
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/