#include "src/include/pmix_config.h"
#include "src/class/pmix_list.h"
#include "pmix_common.h"
#include "src/include/pmix_globals.h"
static void pmix_list_item_construct(pmix_list_item_t *);
static void pmix_list_item_destruct(pmix_list_item_t *);
PMIX_CLASS_INSTANCE(pmix_list_item_t, pmix_object_t, pmix_list_item_construct,
pmix_list_item_destruct);
static void pmix_list_construct(pmix_list_t *);
static void pmix_list_destruct(pmix_list_t *);
PMIX_CLASS_INSTANCE(pmix_list_t, pmix_object_t, pmix_list_construct, pmix_list_destruct);
static void pmix_list_item_construct(pmix_list_item_t *item)
{
item->pmix_list_next = item->pmix_list_prev = NULL;
item->item_free = 1;
#if PMIX_ENABLE_DEBUG
item->pmix_list_item_refcount = 0;
item->pmix_list_item_belong_to = NULL;
#endif
}
static void pmix_list_item_destruct(pmix_list_item_t *item)
{
#if PMIX_ENABLE_DEBUG
assert(0 == item->pmix_list_item_refcount);
assert(NULL == item->pmix_list_item_belong_to);
#endif
PMIX_HIDE_UNUSED_PARAMS(item);
}
static void pmix_list_construct(pmix_list_t *list)
{
#if PMIX_ENABLE_DEBUG
PMIX_CONSTRUCT(&(list->pmix_list_sentinel), pmix_list_item_t);
list->pmix_list_sentinel.pmix_list_item_refcount = 1;
list->pmix_list_sentinel.pmix_list_item_belong_to = list;
#endif
list->pmix_list_sentinel.pmix_list_next = &list->pmix_list_sentinel;
list->pmix_list_sentinel.pmix_list_prev = &list->pmix_list_sentinel;
list->pmix_list_length = 0;
}
static void pmix_list_destruct(pmix_list_t *list)
{
pmix_list_construct(list);
}
bool pmix_list_insert(pmix_list_t *list, pmix_list_item_t *item, long long idx)
{
int i;
volatile pmix_list_item_t *ptr, *next;
if (idx >= (long long) list->pmix_list_length) {
return false;
}
if (0 == idx) {
pmix_list_prepend(list, item);
} else {
#if PMIX_ENABLE_DEBUG
assert(0 == item->pmix_list_item_refcount);
#endif
ptr = list->pmix_list_sentinel.pmix_list_next;
for (i = 0; i < idx - 1; i++)
ptr = ptr->pmix_list_next;
next = ptr->pmix_list_next;
item->pmix_list_next = next;
item->pmix_list_prev = ptr;
next->pmix_list_prev = item;
ptr->pmix_list_next = item;
#if PMIX_ENABLE_DEBUG
item->pmix_list_item_refcount += 1;
assert(1 == item->pmix_list_item_refcount);
item->pmix_list_item_belong_to = list;
#endif
list->pmix_list_length++;
}
return true;
}
static void pmix_list_transfer(pmix_list_item_t *pos, pmix_list_item_t *begin,
pmix_list_item_t *end)
{
volatile pmix_list_item_t *tmp;
if (pos != end) {
end->pmix_list_prev->pmix_list_next = pos;
begin->pmix_list_prev->pmix_list_next = end;
pos->pmix_list_prev->pmix_list_next = begin;
tmp = pos->pmix_list_prev;
pos->pmix_list_prev = end->pmix_list_prev;
end->pmix_list_prev = begin->pmix_list_prev;
begin->pmix_list_prev = tmp;
#if PMIX_ENABLE_DEBUG
{
volatile pmix_list_item_t *item = begin;
while (pos != item) {
item->pmix_list_item_belong_to = pos->pmix_list_item_belong_to;
item = item->pmix_list_next;
assert(NULL != item);
}
}
#endif
}
}
void pmix_list_join(pmix_list_t *thislist, pmix_list_item_t *pos, pmix_list_t *xlist)
{
if (0 != pmix_list_get_size(xlist)) {
pmix_list_transfer(pos, pmix_list_get_first(xlist), pmix_list_get_end(xlist));
thislist->pmix_list_length += xlist->pmix_list_length;
xlist->pmix_list_length = 0;
}
}
void pmix_list_splice(pmix_list_t *thislist, pmix_list_item_t *pos, pmix_list_t *xlist,
pmix_list_item_t *first, pmix_list_item_t *last)
{
size_t change = 0;
pmix_list_item_t *tmp;
if (first != last) {
for (tmp = first; tmp != last; tmp = pmix_list_get_next(tmp)) {
change++;
}
pmix_list_transfer(pos, first, last);
thislist->pmix_list_length += change;
xlist->pmix_list_length -= change;
}
}
int pmix_list_sort(pmix_list_t *list, pmix_list_item_compare_fn_t compare)
{
pmix_list_item_t *item;
pmix_list_item_t **items;
size_t i, index = 0;
if (0 == list->pmix_list_length) {
return PMIX_SUCCESS;
}
items = (pmix_list_item_t **) malloc(sizeof(pmix_list_item_t *) * list->pmix_list_length);
if (NULL == items) {
return PMIX_ERR_OUT_OF_RESOURCE;
}
while (NULL != (item = pmix_list_remove_first(list))) {
items[index++] = item;
}
qsort(items, index, sizeof(pmix_list_item_t *), (int (*)(const void *, const void *)) compare);
for (i = 0; i < index; i++) {
pmix_list_append(list, items[i]);
}
free(items);
return PMIX_SUCCESS;
}