1
1
openmpi/opal/class/ompi_list.c
Jeff Squyres 3a9179a0d7 Initial population of the opal tree
This commit was SVN r6267.
2005-07-02 13:43:20 +00:00

262 строки
6.8 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
* All rights reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "ompi_config.h"
#include "include/constants.h"
#include "class/ompi_list.h"
/*
* List classes
*/
static void ompi_list_item_construct(ompi_list_item_t*);
static void ompi_list_item_destruct(ompi_list_item_t*);
ompi_class_t ompi_list_item_t_class = {
"ompi_list_item_t",
OBJ_CLASS(ompi_object_t),
(ompi_construct_t) ompi_list_item_construct,
(ompi_destruct_t) ompi_list_item_destruct
};
static void ompi_list_construct(ompi_list_t*);
static void ompi_list_destruct(ompi_list_t*);
OBJ_CLASS_INSTANCE(
ompi_list_t,
ompi_object_t,
ompi_list_construct,
ompi_list_destruct
);
/*
*
* ompi_list_link_item_t interface
*
*/
static void ompi_list_item_construct(ompi_list_item_t *item)
{
item->ompi_list_next = item->ompi_list_prev = NULL;
#if OMPI_ENABLE_DEBUG
item->ompi_list_item_refcount = 0;
item->ompi_list_item_belong_to = NULL;
#endif
}
static void ompi_list_item_destruct(ompi_list_item_t *item)
{
#if OMPI_ENABLE_DEBUG
assert( 0 == item->ompi_list_item_refcount );
assert( NULL == item->ompi_list_item_belong_to );
#endif /* OMPI_ENABLE_DEBUG */
}
/*
*
* ompi_list_list_t interface
*
*/
static void ompi_list_construct(ompi_list_t *list)
{
#if OMPI_ENABLE_DEBUG
/* These refcounts should never be used in assertions because they
should never be removed from this list, added to another list,
etc. So set them to sentinel values. */
OBJ_CONSTRUCT( &(list->ompi_list_head), ompi_list_item_t );
list->ompi_list_head.ompi_list_item_refcount = 1;
list->ompi_list_head.ompi_list_item_belong_to = list;
OBJ_CONSTRUCT( &(list->ompi_list_tail), ompi_list_item_t );
list->ompi_list_tail.ompi_list_item_refcount = 1;
list->ompi_list_tail.ompi_list_item_belong_to = list;
#endif
list->ompi_list_head.ompi_list_prev = NULL;
list->ompi_list_head.ompi_list_next = &list->ompi_list_tail;
list->ompi_list_tail.ompi_list_prev = &list->ompi_list_head;
list->ompi_list_tail.ompi_list_next = NULL;
list->ompi_list_length = 0;
}
/*
* Reset all the pointers to be NULL -- do not actually destroy
* anything.
*/
static void ompi_list_destruct(ompi_list_t *list)
{
ompi_list_construct(list);
}
/*
* Insert an item at a specific place in a list
*/
bool ompi_list_insert(ompi_list_t *list, ompi_list_item_t *item, long long idx)
{
/* Adds item to list at index and retains item. */
int i;
volatile ompi_list_item_t *ptr, *next;
if ( idx >= (long long)list->ompi_list_length ) {
return false;
}
if ( 0 == idx )
{
ompi_list_prepend(list, item);
}
else
{
#if OMPI_ENABLE_DEBUG
/* Spot check: ensure that this item is previously on no
lists */
assert(0 == item->ompi_list_item_refcount);
#endif
/* pointer to element 0 */
ptr = list->ompi_list_head.ompi_list_next;
for ( i = 0; i < idx-1; i++ )
ptr = ptr->ompi_list_next;
next = ptr->ompi_list_next;
item->ompi_list_next = next;
item->ompi_list_prev = ptr;
next->ompi_list_prev = item;
ptr->ompi_list_next = item;
#if OMPI_ENABLE_DEBUG
/* Spot check: ensure this item is only on the list that we
just insertted it into */
ompi_atomic_add( &(item->ompi_list_item_refcount), 1 );
assert(1 == item->ompi_list_item_refcount);
item->ompi_list_item_belong_to = list;
#endif
}
list->ompi_list_length++;
return true;
}
static
void
ompi_list_transfer(ompi_list_item_t *pos, ompi_list_item_t *begin,
ompi_list_item_t *end)
{
volatile ompi_list_item_t *tmp;
if (pos != end) {
/* remove [begin, end) */
end->ompi_list_prev->ompi_list_next = pos;
begin->ompi_list_prev->ompi_list_next = end;
pos->ompi_list_prev->ompi_list_next = begin;
/* splice into new position before pos */
tmp = pos->ompi_list_prev;
pos->ompi_list_prev = end->ompi_list_prev;
end->ompi_list_prev = begin->ompi_list_prev;
begin->ompi_list_prev = tmp;
#if OMPI_ENABLE_DEBUG
{
volatile ompi_list_item_t* item = begin;
while( pos != item ) {
item->ompi_list_item_belong_to = pos->ompi_list_item_belong_to;
item = item->ompi_list_next;
assert(NULL != item);
}
}
#endif /* OMPI_ENABLE_DEBUG */
}
}
void
ompi_list_join(ompi_list_t *thislist, ompi_list_item_t *pos,
ompi_list_t *xlist)
{
if (0 != ompi_list_get_size(xlist)) {
ompi_list_transfer(pos, ompi_list_get_first(xlist),
ompi_list_get_end(xlist));
/* fix the sizes */
thislist->ompi_list_length += xlist->ompi_list_length;
xlist->ompi_list_length = 0;
}
}
void
ompi_list_splice(ompi_list_t *thislist, ompi_list_item_t *pos,
ompi_list_t *xlist, ompi_list_item_t *first,
ompi_list_item_t *last)
{
size_t change = 0;
ompi_list_item_t *tmp;
if (first != last) {
/* figure out how many things we are going to move (have to do
* first, since last might be end and then we wouldn't be able
* to run the loop)
*/
for (tmp = first ; tmp != last ; tmp = ompi_list_get_next(tmp)) {
change++;
}
ompi_list_transfer(pos, first, last);
/* fix the sizes */
thislist->ompi_list_length += change;
xlist->ompi_list_length -= change;
}
}
int ompi_list_sort(ompi_list_t* list, ompi_list_item_compare_fn_t compare)
{
ompi_list_item_t* item;
ompi_list_item_t** items;
size_t i, index=0;
if (0 == list->ompi_list_length) {
return OMPI_SUCCESS;
}
items = (ompi_list_item_t**)malloc(sizeof(ompi_list_item_t*) *
list->ompi_list_length);
if (NULL == items) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
while(NULL != (item = ompi_list_remove_first(list))) {
items[index++] = item;
}
qsort(items, index, sizeof(ompi_list_item_t*),
(int(*)(const void*,const void*))compare);
for (i=0; i<index; i++) {
ompi_list_append(list,items[i]);
}
free(items);
return OMPI_SUCCESS;
}