xref: /OK3568_Linux_fs/external/xserver/hw/xquartz/xpr/x-list.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* x-list.c
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person
6*4882a593Smuzhiyun  * obtaining a copy of this software and associated documentation files
7*4882a593Smuzhiyun  * (the "Software"), to deal in the Software without restriction,
8*4882a593Smuzhiyun  * including without limitation the rights to use, copy, modify, merge,
9*4882a593Smuzhiyun  * publish, distribute, sublicense, and/or sell copies of the Software,
10*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so,
11*4882a593Smuzhiyun  * subject to the following conditions:
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be
14*4882a593Smuzhiyun  * included in all copies or substantial portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*4882a593Smuzhiyun  * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
20*4882a593Smuzhiyun  * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21*4882a593Smuzhiyun  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*4882a593Smuzhiyun  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Except as contained in this notice, the name(s) of the above
26*4882a593Smuzhiyun  * copyright holders shall not be used in advertising or otherwise to
27*4882a593Smuzhiyun  * promote the sale, use or other dealings in this Software without
28*4882a593Smuzhiyun  * prior written authorization.
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
32*4882a593Smuzhiyun #include <dix-config.h>
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include "x-list.h"
36*4882a593Smuzhiyun #include <stdlib.h>
37*4882a593Smuzhiyun #include <assert.h>
38*4882a593Smuzhiyun #include <pthread.h>
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* Allocate in ~4k blocks */
41*4882a593Smuzhiyun #define NODES_PER_BLOCK 508
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun typedef struct x_list_block_struct x_list_block;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct x_list_block_struct {
46*4882a593Smuzhiyun     x_list l[NODES_PER_BLOCK];
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun static x_list *freelist;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static pthread_mutex_t freelist_lock = PTHREAD_MUTEX_INITIALIZER;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static inline void
list_free_1(x_list * node)54*4882a593Smuzhiyun list_free_1(x_list *node)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun     node->next = freelist;
57*4882a593Smuzhiyun     freelist = node;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun X_EXTERN void
X_PFX(list_free_1)61*4882a593Smuzhiyun X_PFX(list_free_1) (x_list * node) {
62*4882a593Smuzhiyun     assert(node != NULL);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun     pthread_mutex_lock(&freelist_lock);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun     list_free_1(node);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun     pthread_mutex_unlock(&freelist_lock);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun X_EXTERN void
X_PFX(list_free)72*4882a593Smuzhiyun X_PFX(list_free) (x_list * lst) {
73*4882a593Smuzhiyun     x_list *next;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun     pthread_mutex_lock(&freelist_lock);
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun     for (; lst != NULL; lst = next) {
78*4882a593Smuzhiyun         next = lst->next;
79*4882a593Smuzhiyun         list_free_1(lst);
80*4882a593Smuzhiyun     }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     pthread_mutex_unlock(&freelist_lock);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_prepend)86*4882a593Smuzhiyun X_PFX(list_prepend) (x_list * lst, void *data) {
87*4882a593Smuzhiyun     x_list *node;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun     pthread_mutex_lock(&freelist_lock);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun     if (freelist == NULL) {
92*4882a593Smuzhiyun         x_list_block *b;
93*4882a593Smuzhiyun         int i;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun         b = malloc(sizeof(x_list_block));
96*4882a593Smuzhiyun         assert(b != NULL);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun         for (i = 0; i < NODES_PER_BLOCK - 1; i++)
99*4882a593Smuzhiyun             b->l[i].next = &(b->l[i + 1]);
100*4882a593Smuzhiyun         b->l[i].next = NULL;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun         freelist = b->l;
103*4882a593Smuzhiyun     }
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     node = freelist;
106*4882a593Smuzhiyun     freelist = node->next;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun     pthread_mutex_unlock(&freelist_lock);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     node->next = lst;
111*4882a593Smuzhiyun     node->data = data;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun     return node;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_append)117*4882a593Smuzhiyun X_PFX(list_append) (x_list * lst, void *data) {
118*4882a593Smuzhiyun     x_list *head = lst;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun     if (lst == NULL)
121*4882a593Smuzhiyun         return X_PFX(list_prepend) (NULL, data);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun     while (lst->next != NULL)
124*4882a593Smuzhiyun         lst = lst->next;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     lst->next = X_PFX(list_prepend) (NULL, data);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     return head;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_reverse)132*4882a593Smuzhiyun X_PFX(list_reverse) (x_list * lst) {
133*4882a593Smuzhiyun     x_list *head = NULL, *next;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun     while (lst != NULL)
136*4882a593Smuzhiyun     {
137*4882a593Smuzhiyun         next = lst->next;
138*4882a593Smuzhiyun         lst->next = head;
139*4882a593Smuzhiyun         head = lst;
140*4882a593Smuzhiyun         lst = next;
141*4882a593Smuzhiyun     }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     return head;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_find)147*4882a593Smuzhiyun X_PFX(list_find) (x_list * lst, void *data) {
148*4882a593Smuzhiyun     for (; lst != NULL; lst = lst->next) {
149*4882a593Smuzhiyun         if (lst->data == data)
150*4882a593Smuzhiyun             return lst;
151*4882a593Smuzhiyun     }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun     return NULL;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_nth)157*4882a593Smuzhiyun X_PFX(list_nth) (x_list * lst, int n) {
158*4882a593Smuzhiyun     while (n-- > 0 && lst != NULL)
159*4882a593Smuzhiyun         lst = lst->next;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun     return lst;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_pop)165*4882a593Smuzhiyun X_PFX(list_pop) (x_list * lst, void **data_ret) {
166*4882a593Smuzhiyun     void *data = NULL;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     if (lst != NULL) {
169*4882a593Smuzhiyun         x_list *tem = lst;
170*4882a593Smuzhiyun         data = lst->data;
171*4882a593Smuzhiyun         lst = lst->next;
172*4882a593Smuzhiyun         X_PFX(list_free_1) (tem);
173*4882a593Smuzhiyun     }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun     if (data_ret != NULL)
176*4882a593Smuzhiyun         *data_ret = data;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun     return lst;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_filter)182*4882a593Smuzhiyun X_PFX(list_filter) (x_list * lst,
183*4882a593Smuzhiyun                     int (*pred)(void *item, void *data), void *data) {
184*4882a593Smuzhiyun     x_list *ret = NULL, *node;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun     for (node = lst; node != NULL; node = node->next) {
187*4882a593Smuzhiyun         if ((*pred)(node->data, data))
188*4882a593Smuzhiyun             ret = X_PFX(list_prepend) (ret, node->data);
189*4882a593Smuzhiyun     }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun     return X_PFX(list_reverse) (ret);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_map)195*4882a593Smuzhiyun X_PFX(list_map) (x_list * lst,
196*4882a593Smuzhiyun                  void *(*fun)(void *item, void *data), void *data) {
197*4882a593Smuzhiyun     x_list *ret = NULL, *node;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     for (node = lst; node != NULL; node = node->next) {
200*4882a593Smuzhiyun         X_PFX(list_prepend) (ret, fun(node->data, data));
201*4882a593Smuzhiyun     }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     return X_PFX(list_reverse) (ret);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_copy)207*4882a593Smuzhiyun X_PFX(list_copy) (x_list * lst) {
208*4882a593Smuzhiyun     x_list *copy = NULL;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     for (; lst != NULL; lst = lst->next) {
211*4882a593Smuzhiyun         copy = X_PFX(list_prepend) (copy, lst->data);
212*4882a593Smuzhiyun     }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun     return X_PFX(list_reverse) (copy);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_remove)218*4882a593Smuzhiyun X_PFX(list_remove) (x_list * lst, void *data) {
219*4882a593Smuzhiyun     x_list **ptr, *node;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     for (ptr = &lst; *ptr != NULL;) {
222*4882a593Smuzhiyun         node = *ptr;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun         if (node->data == data) {
225*4882a593Smuzhiyun             *ptr = node->next;
226*4882a593Smuzhiyun             X_PFX(list_free_1) (node);
227*4882a593Smuzhiyun         }
228*4882a593Smuzhiyun         else
229*4882a593Smuzhiyun             ptr = &((*ptr)->next);
230*4882a593Smuzhiyun     }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     return lst;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun X_EXTERN unsigned int
X_PFX(list_length)236*4882a593Smuzhiyun X_PFX(list_length) (x_list * lst) {
237*4882a593Smuzhiyun     unsigned int n;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     n = 0;
240*4882a593Smuzhiyun     for (; lst != NULL; lst = lst->next)
241*4882a593Smuzhiyun         n++;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun     return n;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun X_EXTERN void
X_PFX(list_foreach)247*4882a593Smuzhiyun X_PFX(list_foreach) (x_list * lst,
248*4882a593Smuzhiyun                      void (*fun)(void *data, void *user_data),
249*4882a593Smuzhiyun                      void *user_data) {
250*4882a593Smuzhiyun     for (; lst != NULL; lst = lst->next) {
251*4882a593Smuzhiyun         (*fun)(lst->data, user_data);
252*4882a593Smuzhiyun     }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static x_list *
list_sort_1(x_list * lst,int length,int (* less)(const void *,const void *))256*4882a593Smuzhiyun list_sort_1(x_list *lst, int length,
257*4882a593Smuzhiyun             int (*less)(const void *, const void *))
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun     x_list *mid, *ptr;
260*4882a593Smuzhiyun     x_list *out_head, *out;
261*4882a593Smuzhiyun     int mid_point, i;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun     /* This is a standard (stable) list merge sort */
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     if (length < 2)
266*4882a593Smuzhiyun         return lst;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     /* Calculate the halfway point. Split the list into two sub-lists. */
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun     mid_point = length / 2;
271*4882a593Smuzhiyun     ptr = lst;
272*4882a593Smuzhiyun     for (i = mid_point - 1; i > 0; i--)
273*4882a593Smuzhiyun         ptr = ptr->next;
274*4882a593Smuzhiyun     mid = ptr->next;
275*4882a593Smuzhiyun     ptr->next = NULL;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun     /* Sort each sub-list. */
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     lst = list_sort_1(lst, mid_point, less);
280*4882a593Smuzhiyun     mid = list_sort_1(mid, length - mid_point, less);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     /* Then merge them back together. */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     assert(lst != NULL && mid != NULL);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     if ((*less)(mid->data, lst->data))
287*4882a593Smuzhiyun         out = out_head = mid, mid = mid->next;
288*4882a593Smuzhiyun     else
289*4882a593Smuzhiyun         out = out_head = lst, lst = lst->next;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun     while (lst != NULL && mid != NULL)
292*4882a593Smuzhiyun     {
293*4882a593Smuzhiyun         if ((*less)(mid->data, lst->data))
294*4882a593Smuzhiyun             out = out->next = mid, mid = mid->next;
295*4882a593Smuzhiyun         else
296*4882a593Smuzhiyun             out = out->next = lst, lst = lst->next;
297*4882a593Smuzhiyun     }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     if (lst != NULL)
300*4882a593Smuzhiyun         out->next = lst;
301*4882a593Smuzhiyun     else
302*4882a593Smuzhiyun         out->next = mid;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun     return out_head;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun X_EXTERN x_list *
X_PFX(list_sort)308*4882a593Smuzhiyun X_PFX(list_sort) (x_list * lst, int (*less)(const void *, const void *)) {
309*4882a593Smuzhiyun     int length;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     length = X_PFX(list_length) (lst);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun     return list_sort_1(lst, length, less);
314*4882a593Smuzhiyun }
315