1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* 2005-02-04 Paul McCullagh
24
#include "xt_config.h"
26
#include "pthread_xt.h"
27
#include "thread_xt.h"
28
#include "sortedlist_xt.h"
30
XTSortedListPtr xt_new_sortedlist_ns(u_int item_size, u_int grow_size, XTCompareFunc comp_func, void *thunk, XTFreeFunc free_func)
34
if (!(sl = (XTSortedListPtr) xt_calloc_ns(sizeof(XTSortedListRec))))
36
sl->sl_item_size = item_size;
37
sl->sl_grow_size = grow_size;
38
sl->sl_comp_func = comp_func;
40
sl->sl_free_func = free_func;
41
sl->sl_current_size = 0;
45
XTSortedListPtr xt_new_sortedlist(XTThreadPtr self, u_int item_size, u_int initial_size, u_int grow_size, XTCompareFunc comp_func, void *thunk, XTFreeFunc free_func, xtBool with_lock, xtBool with_cond)
49
sl = (XTSortedListPtr) xt_calloc(self, sizeof(XTSortedListRec));
50
xt_init_sortedlist(self, sl, item_size, initial_size, grow_size, comp_func, thunk, free_func, with_lock, with_cond);
54
xtPublic void xt_init_sortedlist(XTThreadPtr self, XTSortedListPtr sl, u_int item_size, u_int initial_size, u_int grow_size, XTCompareFunc comp_func, void *thunk, XTFreeFunc free_func, xtBool with_lock, xtBool with_cond)
56
sl->sl_item_size = item_size;
57
sl->sl_grow_size = grow_size;
58
sl->sl_comp_func = comp_func;
60
sl->sl_free_func = free_func;
61
sl->sl_current_size = initial_size;
65
sl->sl_data = (char *) xt_malloc(self, initial_size * item_size);
74
if (with_lock || with_cond) {
75
sl->sl_lock = (xt_mutex_type *) xt_calloc(self, sizeof(xt_mutex_type));
77
xt_init_mutex_with_autoname(self, sl->sl_lock);
80
xt_free(self, sl->sl_lock);
82
xt_free_sortedlist(self, sl);
89
sl->sl_cond = (xt_cond_type *) xt_calloc(self, sizeof(xt_cond_type));
91
xt_init_cond(self, sl->sl_cond);
94
xt_free(self, sl->sl_cond);
96
xt_free_sortedlist(self, sl);
103
xtPublic xtBool xt_init_sortedlist_ns(XTSortedListPtr sl, u_int item_size, u_int initial_size, u_int grow_size, XTCompareFunc comp_func, void *thunk, XTFreeFunc free_func, xtBool with_lock, xtBool with_cond)
105
memset(sl, 0, sizeof(XTSortedListRec));
106
sl->sl_item_size = item_size;
107
sl->sl_grow_size = grow_size;
108
sl->sl_comp_func = comp_func;
109
sl->sl_thunk = thunk;
110
sl->sl_free_func = free_func;
111
sl->sl_current_size = initial_size;
114
if (!(sl->sl_data = (char *) xt_malloc_ns(initial_size * item_size)))
118
if (with_lock || with_cond) {
119
if (!(sl->sl_lock = (xt_mutex_type *) xt_calloc_ns(sizeof(xt_mutex_type))))
121
if (!xt_init_mutex_with_autoname(NULL, sl->sl_lock))
126
if (!(sl->sl_cond = (xt_cond_type *) xt_calloc_ns(sizeof(xt_cond_type))))
128
if (!xt_init_cond(NULL, sl->sl_cond))
135
xt_free_sortedlist(NULL, sl);
139
xtPublic void xt_empty_sortedlist(XTThreadPtr self, XTSortedListPtr sl)
142
xt_lock_mutex(self, sl->sl_lock);
144
if (sl->sl_free_func) {
145
while (sl->sl_usage_count > 0) {
146
sl->sl_usage_count--;
147
if (sl->sl_free_func)
148
(*sl->sl_free_func)(self, sl->sl_thunk, &sl->sl_data[sl->sl_usage_count * sl->sl_item_size]);
152
sl->sl_usage_count = 0;
155
xt_unlock_mutex(self, sl->sl_lock);
158
xtPublic void xt_clear_sortedlist(XTSortedListPtr sl)
161
xt_free_ns(sl->sl_data);
165
xt_free_mutex(sl->sl_lock);
166
xt_free_ns(sl->sl_lock);
169
xt_free_cond(sl->sl_cond);
170
xt_free_ns(sl->sl_cond);
174
xtPublic void xt_free_sortedlist(XTThreadPtr self, XTSortedListPtr sl)
176
xt_empty_sortedlist(self, sl);
177
xt_clear_sortedlist(sl);
181
xtPublic void *xt_sl_find(XTThreadPtr self, XTSortedListPtr sl, void *key)
186
if (sl->sl_usage_count == 0)
188
else if (sl->sl_usage_count == 1) {
189
if ((*sl->sl_comp_func)(self, sl->sl_thunk, key, sl->sl_data) == 0)
193
result = xt_bsearch(self, key, sl->sl_data, sl->sl_usage_count, sl->sl_item_size, &idx, sl->sl_thunk, sl->sl_comp_func);
197
/* This function is the same as find, but it also returns the
198
* index position for the item.
200
* If the item is not in the list, then it returns the index at which the item
201
* should be inserted.
203
xtPublic void *xt_sl_search(XTThreadPtr self, size_t *idx, XTSortedListPtr sl, void *key)
205
if (sl->sl_usage_count == 0) {
209
else if (sl->sl_usage_count == 1) {
212
if ((r = (*sl->sl_comp_func)(self, sl->sl_thunk, key, sl->sl_data)) == 0) {
222
return xt_bsearch(self, key, sl->sl_data, sl->sl_usage_count, sl->sl_item_size, idx, sl->sl_thunk, sl->sl_comp_func);
227
* 1 = Value inserted.
228
* 2 = Value not inserted, already in the list (returned value is index + 2).
229
* 0 = An error occurred.
231
xtPublic int xt_sl_insert(XTThreadPtr self, XTSortedListPtr sl, void *key, void *data)
235
if (sl->sl_usage_count == 0)
237
else if (sl->sl_usage_count == 1) {
240
if ((r = (*sl->sl_comp_func)(self, sl->sl_thunk, key, sl->sl_data)) == 0) {
241
if (sl->sl_free_func)
242
(*sl->sl_free_func)(self, sl->sl_thunk, data);
251
if (xt_bsearch(self, key, sl->sl_data, sl->sl_usage_count, sl->sl_item_size, &idx, sl->sl_thunk, sl->sl_comp_func)) {
252
if (sl->sl_free_func)
253
(*sl->sl_free_func)(self, sl->sl_thunk, data);
257
if (sl->sl_usage_count == sl->sl_current_size) {
258
if (!xt_realloc_ns((void **) &sl->sl_data, (sl->sl_current_size + sl->sl_grow_size) * sl->sl_item_size)) {
259
if (sl->sl_free_func)
260
(*sl->sl_free_func)(self, sl->sl_thunk, data);
265
sl->sl_current_size = sl->sl_current_size + sl->sl_grow_size;
267
XT_MEMMOVE(sl->sl_data, &sl->sl_data[(idx+1) * sl->sl_item_size], &sl->sl_data[idx * sl->sl_item_size], (sl->sl_usage_count-idx) * sl->sl_item_size);
268
XT_MEMCPY(sl->sl_data, &sl->sl_data[idx * sl->sl_item_size], data, sl->sl_item_size);
269
sl->sl_usage_count++;
273
xtPublic xtBool xt_sl_insert_item_at(XTThreadPtr self, XTSortedListPtr sl, size_t idx, void *data)
275
ASSERT(idx <= sl->sl_usage_count);
276
if (sl->sl_usage_count == sl->sl_current_size) {
277
if (!xt_realloc_ns((void **) &sl->sl_data, (sl->sl_current_size + sl->sl_grow_size) * sl->sl_item_size)) {
278
if (sl->sl_free_func)
279
(*sl->sl_free_func)(self, sl->sl_thunk, data);
284
sl->sl_current_size = sl->sl_current_size + sl->sl_grow_size;
286
XT_MEMMOVE(sl->sl_data, &sl->sl_data[(idx+1) * sl->sl_item_size], &sl->sl_data[idx * sl->sl_item_size], (sl->sl_usage_count-idx) * sl->sl_item_size);
287
XT_MEMCPY(sl->sl_data, &sl->sl_data[idx * sl->sl_item_size], data, sl->sl_item_size);
288
sl->sl_usage_count++;
292
xtPublic xtBool xt_sl_delete(XTThreadPtr self, XTSortedListPtr sl, void *key)
297
if (sl->sl_usage_count == 0)
299
if (sl->sl_usage_count == 1) {
300
if ((*sl->sl_comp_func)(self, sl->sl_thunk, key, sl->sl_data) != 0)
303
result = sl->sl_data;
306
if (!(result = xt_bsearch(self, key, sl->sl_data, sl->sl_usage_count, sl->sl_item_size, &idx, sl->sl_thunk, sl->sl_comp_func)))
309
if (sl->sl_free_func)
310
(*sl->sl_free_func)(self, sl->sl_thunk, result);
311
sl->sl_usage_count--;
312
XT_MEMMOVE(sl->sl_data, &sl->sl_data[idx * sl->sl_item_size], &sl->sl_data[(idx+1) * sl->sl_item_size], (sl->sl_usage_count-idx) * sl->sl_item_size);
316
xtPublic void xt_sl_delete_item_at(XTThreadPtr self, XTSortedListPtr sl, size_t idx)
320
if (idx >= sl->sl_usage_count)
322
result = &sl->sl_data[idx * sl->sl_item_size];
323
if (sl->sl_free_func)
324
(*sl->sl_free_func)(self, sl->sl_thunk, result);
325
sl->sl_usage_count--;
326
XT_MEMMOVE(sl->sl_data, &sl->sl_data[idx * sl->sl_item_size], &sl->sl_data[(idx+1) * sl->sl_item_size], (sl->sl_usage_count-idx) * sl->sl_item_size);
329
xtPublic void xt_sl_remove_from_front(struct XTThread *XT_UNUSED(self), XTSortedListPtr sl, size_t items)
331
if (sl->sl_usage_count <= items)
332
xt_sl_set_size(sl, 0);
334
XT_MEMMOVE(sl->sl_data, sl->sl_data, &sl->sl_data[items * sl->sl_item_size], (sl->sl_usage_count-items) * sl->sl_item_size);
335
sl->sl_usage_count -= items;
339
xtPublic void xt_sl_delete_from_info(XTThreadPtr self, XTSortedListInfoPtr li_undo)
341
xt_sl_delete(self, li_undo->li_sl, li_undo->li_key);
344
xtPublic void xt_sl_set_size(XTSortedListPtr sl, size_t new_size)
346
sl->sl_usage_count = new_size;
347
if (sl->sl_usage_count + sl->sl_grow_size <= sl->sl_current_size) {
350
curr_size = sl->sl_usage_count;
351
if (curr_size < sl->sl_grow_size)
352
curr_size = sl->sl_grow_size;
354
if (xt_realloc(NULL, (void **) &sl->sl_data, curr_size * sl->sl_item_size))
355
sl->sl_current_size = curr_size;
359
xtPublic void *xt_sl_item_at(XTSortedListPtr sl, size_t idx)
361
if (idx < sl->sl_usage_count)
362
return &sl->sl_data[idx * sl->sl_item_size];
366
xtPublic void *xt_sl_last_item(XTSortedListPtr sl)
368
if (sl->sl_usage_count > 0)
369
return xt_sl_item_at(sl, sl->sl_usage_count - 1);
373
xtPublic void *xt_sl_first_item(XTSortedListPtr sl)
375
if (sl->sl_usage_count > 0)
376
return xt_sl_item_at(sl, 0);
380
xtPublic xtBool xt_sl_lock(XTThreadPtr self, XTSortedListPtr sl)
384
if (sl->sl_locker != self)
385
r = xt_lock_mutex(self, sl->sl_lock);
387
sl->sl_locker = self;
393
xtPublic void xt_sl_unlock(XTThreadPtr self, XTSortedListPtr sl)
395
ASSERT(!self || sl->sl_locker == self);
396
ASSERT(sl->sl_lock_count > 0);
399
if (!sl->sl_lock_count) {
400
sl->sl_locker = NULL;
401
xt_unlock_mutex(self, sl->sl_lock);
405
xtPublic void xt_sl_lock_ns(XTSortedListPtr sl, XTThreadPtr thread)
407
if (!thread || sl->sl_locker != thread) {
408
xt_lock_mutex_ns(sl->sl_lock);
409
ASSERT_NS(sl->sl_locker == NULL);
410
sl->sl_locker = thread;
415
xtPublic void xt_sl_unlock_ns(XTSortedListPtr sl)
417
ASSERT_NS(!sl->sl_locker || sl->sl_locker == xt_get_self());
418
ASSERT_NS(sl->sl_lock_count > 0);
421
if (!sl->sl_lock_count) {
422
sl->sl_locker = NULL;
423
xt_unlock_mutex_ns(sl->sl_lock);
427
xtPublic void xt_sl_wait(XTThreadPtr self, XTSortedListPtr sl)
429
xt_wait_cond(self, sl->sl_cond, sl->sl_lock);
432
xtPublic xtBool xt_sl_signal(XTThreadPtr self, XTSortedListPtr sl)
434
return xt_signal_cond(self, sl->sl_cond);
437
xtPublic void xt_sl_broadcast(XTThreadPtr self, XTSortedListPtr sl)
439
xt_broadcast_cond(self, sl->sl_cond);
443
* -----------------------------------------------------------------------
447
void XTPointerList::pl_init(XTThreadPtr self)
453
void XTPointerList::pl_exit()
455
xt_clear_sortedlist(&pl_sortedlist);
458
static int sl_cmp_ptr(struct XTThread *XT_UNUSED(self), register const void *XT_UNUSED(thunk), register const void *a, register const void *b)
460
void **b_ptr = (void **) b;
469
xtBool XTPointerList::pl_init_ns()
471
return xt_init_sortedlist_ns(&pl_sortedlist, sizeof(void *), 2, 4, sl_cmp_ptr, NULL, NULL, FALSE, FALSE);
475
* Same as init, but cannot fail because nothing is allocated.
477
void XTPointerList::pl_setup_ns()
479
xt_init_sortedlist_ns(&pl_sortedlist, sizeof(void *), 0, 4, sl_cmp_ptr, NULL, NULL, FALSE, FALSE);
482
xtBool XTPointerList::pl_add_pointer(void *ptr)
484
return xt_sl_insert(NULL, &pl_sortedlist, ptr, &ptr);
488
* Return TRUE of the pointer was on the list.
490
xtBool XTPointerList::pl_remove_pointer(void *ptr)
492
return xt_sl_delete(NULL, &pl_sortedlist, ptr);
496
* Return NULL if the index is out of range.
498
void *XTPointerList::pl_get_pointer(u_int index)
502
if ((p_ptr = (void **) xt_sl_item_at(&pl_sortedlist, index)))
507
void XTPointerList::pl_clear()
509
pl_sortedlist.sl_usage_count = 0;
512
u_int XTPointerList::pl_size()
514
return pl_sortedlist.sl_usage_count;
517
xtBool XTPointerList::pl_is_empty()
519
return pl_sortedlist.sl_usage_count == 0;