void * list_pick_value(linked_list_t *list, size_t pos) { list_entry_t *entry = pick_entry(list, pos); if(entry) return entry->value; return NULL; }
static void file_unlink_file(struct file_info *file) { struct dir_entry_info *entry; entry = pick_entry(file); if (!entry) return; file_unlink(entry); }
void list_sort(linked_list_t *list, list_comparator_callback_t comparator) { MUTEX_LOCK(list->lock); list_entry_t *pivot = pick_entry(list, (list->length/2) - 1); list_quick_sort(list->head, list->tail, pivot, list->length, comparator); list->cur = NULL; list->pos = 0; MUTEX_UNLOCK(list->lock); }
/* return old value at pos */ void * list_subst_value(linked_list_t *list, size_t pos, void *newval) { void *old_value = NULL; MUTEX_LOCK(list->lock); list_entry_t *entry = pick_entry(list, pos); if (entry) { old_value = entry->value; entry->value = newval; } MUTEX_UNLOCK(list->lock); return old_value; }
void * list_set_value(linked_list_t *list, uint32_t pos, void *newval) { void *old_value = NULL; MUTEX_LOCK(&list->lock); list_entry_t *entry = pick_entry(list, pos); if (entry) { old_value = entry->value; entry->value = newval; } else { list_insert_value(list, newval, pos); } MUTEX_UNLOCK(&list->lock); return old_value; }
/* * Instert an entry at a specified position in a linked_list_t */ static inline int insert_entry(linked_list_t *list, list_entry_t *entry, size_t pos) { list_entry_t *prev, *next; int ret = -1; MUTEX_LOCK(list->lock); if(pos == 0) { ret = unshift_entry(list, entry); } else if(pos == list->length) { ret = push_entry(list, entry); } else if (pos > list->length) { unsigned int i; for (i = list->length; i < pos; i++) { list_entry_t *emptyEntry = create_entry(); if (!emptyEntry || push_entry(list, emptyEntry) != 0) { if (emptyEntry) destroy_entry(emptyEntry); MUTEX_UNLOCK(list->lock); return -1; } } ret = push_entry(list, entry); } if (ret == 0) { MUTEX_UNLOCK(list->lock); return ret; } prev = pick_entry(list, pos-1); if(prev) { next = prev->next; prev->next = entry; entry->prev = prev; entry->next = next; if (next) next->prev = entry; list->length++; ret = 0; } MUTEX_UNLOCK(list->lock); return ret; }
int slice_foreach_value(slice_t *slice, int (*item_handler)(void *item, size_t idx, void *user), void *user) { linked_list_t *list = slice->list; MUTEX_LOCK(list->lock); size_t idx = 0; list_entry_t *e = pick_entry(list, slice->offset); while(e && idx < slice->length) { int rc = item_handler(e->value, idx++, user); if (rc == 0) { break; } else if (rc == -1 || rc == -2) { list_entry_t *d = e; e = e->next; if (list->head == list->tail && list->tail == d) { list->head = list->tail = NULL; } else if (d == list->head) { list->head = d->next; list->head->prev = NULL; } else if (d == list->tail) { list->tail = d->prev; list->tail->next = NULL; } else { e->prev = d->prev; e->prev->next = e; } d->list = NULL; if (list->cur == d) list->cur = NULL; list->length--; slice->length--; // the callback got the value and will take care of releasing it destroy_entry(d); if (rc == -2) // -2 means : remove and stop the iteration break; // -1 instead means that we still want to remove the item // but we also want to go ahead with the iteration } else { e = e->next; } } MUTEX_UNLOCK(list->lock); return idx; }
/* XXX - POSSIBLE RACE CONDITION BETWEEN pick_entry and the actual removal */ static inline list_entry_t *remove_entry(linked_list_t *list, size_t pos) { list_entry_t *next, *prev; list_entry_t *entry = pick_entry(list, pos); MUTEX_LOCK(list->lock); if(entry) { prev = entry->prev; next = entry->next; if (pos == 0) list->head = next; else if (pos == list->length - 1) list->tail = prev; if(prev) prev->next = next; if(next) next->prev = prev; list->length--; entry->list = NULL; entry->prev = NULL; entry->next = NULL; if (list->cur == entry) { list->cur = NULL; list->pos = 0; } else if (list->pos > pos) { list->pos--; } MUTEX_UNLOCK(list->lock); return entry; } MUTEX_UNLOCK(list->lock); return NULL; }