1
1

* Modifications to the ompi_list_t interface and test suite

- added ompi_list_splice and ompi_list_join, which are multi-list
    manipulation functions similar to the splice functions in the STL
    list interface
  - added ompi_list_is_empty() for O(1) testing of for an empty list
  - added note that sometime in the future, ompi_list_get_size() may
    change to O(N) complexity.  DID NOT CHANGE THE FUNCTION IN ANY WAY.

If you are writing new code that needs to check for an empty list, please
use ompi_list_is_empty() rather than ompi_list_get_size() as is_empty()
will always be an O(1) operation (I can't see how you could make it
impossible to make it O(1), so this seems like a safe claim).

This commit was SVN r2186.
Этот коммит содержится в:
Brian Barrett 2004-08-17 19:31:07 +00:00
родитель 08de49cc4a
Коммит c5ebf49f41
3 изменённых файлов: 213 добавлений и 9 удалений

Просмотреть файл

@ -106,3 +106,66 @@ bool ompi_list_insert(ompi_list_t *list, ompi_list_item_t *item, long long idx)
return true;
}
static
void
ompi_list_transfer(ompi_list_item_t *pos, ompi_list_item_t *begin,
ompi_list_item_t *end)
{
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;
}
}
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;
}
}

Просмотреть файл

@ -28,6 +28,7 @@
#define OMPI_LIST_H
#include <stdio.h>
#include <stdlib.h>
#include "class/ompi_object.h"
/**
@ -108,22 +109,24 @@ typedef struct ompi_list_t ompi_list_t;
/**
* Return the number of items in a list (O(1) operation)
* Check for empty list
*
* @param list The list container
*
* @returns The size of the list (size_t)
* @returns true if list's size is 0, false otherwise
*
* This is an O(1) lookup to return the size of the list.
* This is an O(1) operation.
*
* This is an inlined function in compilers that support inlining, so
* it's usually a cheap operation.
* This is an inlined function in compilers that support inlining,
* so it's usually a cheap operation.
*/
static inline size_t ompi_list_get_size(ompi_list_t* list)
static inline bool ompi_list_is_empty(ompi_list_t* list)
{
return list->ompi_list_length;
return (list->ompi_list_head.ompi_list_next ==
&(list->ompi_list_tail));
}
/**
* Return the first item on the list (does not remove it).
*
@ -206,6 +209,50 @@ static inline ompi_list_item_t* ompi_list_get_end(ompi_list_t* list)
return &(list->ompi_list_tail);
}
/**
* Return the number of items in a list
*
* @param list The list container
*
* @returns The size of the list (size_t)
*
* This is an O(1) lookup to return the size of the list.
*
* This is an inlined function in compilers that support inlining, so
* it's usually a cheap operation.
*
* \warning In the future, this may become an O(N) operation. If you
* only need to check for comparison with 0, please use \c
* ompi_list_is_empty, which will always be an O(1) operation.
*/
static inline size_t ompi_list_get_size(ompi_list_t* list)
{
#if OMPI_ENABLE_DEBUG && 0
/* not sure if we really want this running in devel, as it does
* slow things down. Wanted for development of splice / join to
* make sure length was reset properly
*/
size_t check_len = 0;
ompi_list_item_t *item;
for (item = ompi_list_get_first(list) ;
item != ompi_list_get_end(list) ;
item = ompi_list_get_next(item)) {
check_len++;
}
if (check_len != list->ompi_list_length) {
fprintf(stderr," Error :: ompi_list_get_size - ompi_list_length does not match actual list length\n");
fflush(stderr);
abort();
}
#endif
return list->ompi_list_length;
}
/**
* Remove an item from a list.
*
@ -449,6 +496,56 @@ extern "C" {
*/
bool ompi_list_insert(ompi_list_t *list, ompi_list_item_t *item,
long long idx);
/**
* Join a list into another list
*
* @param thislist List container for list being operated on
* @param pos List item in \c thislist marking the position before
* which items are inserted
* @param xlist List container for list being spliced from
*
* Join a list into another list. All of the elements of \c xlist
* are inserted before \c pos and removed from \c xlist.
*
* This operation is an O(1) operation. Both \c thislist and \c
* xlist must be valid list containsers. \c xlist will be empty
* but valid after the call. All pointers to \c ompi_list_item_t
* containers remain valid, including those that point to elements
* in \c xlist.
*/
void ompi_list_join(ompi_list_t *thislist, ompi_list_item_t *pos,
ompi_list_t *xlist);
/**
* Splice a list into another list
*
* @param thislist List container for list being operated on
* @param pos List item in \c thislist marking the position before
* which items are inserted
* @param xlist List container for list being spliced from
* @param first List item in \c xlist marking the start of elements
* to be copied into \c thislist
* @param last List item in \c xlist marking the end of elements
* to be copied into \c thislist
*
* Splice a subset of a list into another list. The \c [first,
* last) elements of \c xlist are moved into \c thislist,
* inserting them before \c pos. \c pos must be a valid iterator
* in \c thislist and \c [first, last) must be a valid range in \c
* xlist. \c postition must not be in the range \c [first, last).
* It is, however, valid for \c xlist and \c thislist to be the
* same list.
*
* This is an O(N) operation because the length of both lists must
* be recomputed.
*/
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);
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif

Просмотреть файл

@ -20,15 +20,17 @@ typedef struct test_data {
int main(int argc, char **argv)
{
/* local variables */
ompi_list_t list;
size_t list_size;
ompi_list_t list, x;
size_t list_size, tmp_size_1, tmp_size_2;
int size_elements,i,indx,error_cnt;
test_data_t *elements, *ele;
ompi_list_item_t *item;
test_init("ompi_list_t");
/* initialize list */
OBJ_CONSTRUCT(&list, ompi_list_t);
OBJ_CONSTRUCT(&x, ompi_list_t);
/* check length of list */
list_size=ompi_list_get_size(&list);
@ -38,6 +40,13 @@ int main(int argc, char **argv)
test_failure(" ompi_list_get_size");
}
/* check for empty */
if (ompi_list_is_empty(&list)) {
test_success();
} else {
test_failure(" ompi_list_is_empty(empty list)");
}
/* create test elements */
size_elements=4;
elements=(test_data_t *)malloc(sizeof(test_data_t)*size_elements);
@ -57,6 +66,13 @@ int main(int argc, char **argv)
test_failure(" populating list");
}
/* checking for empty on non-empty list */
if (!ompi_list_is_empty(&list)) {
test_success();
} else {
test_failure(" ompi_list_is_empty(non-empty list)");
}
/* check that list is ordered as expected */
i=0;
error_cnt=0;
@ -277,5 +293,33 @@ int main(int argc, char **argv)
test_failure(" error in list order - ompi_list_remove_item ");
}
/* test the splice and join functions */
list_size = ompi_list_get_size(&list);
for (i = 0, item = ompi_list_get_first(&list) ;
i < list_size / 2 ; ++i, item = ompi_list_get_next(item)) {
}
ompi_list_splice(&x, ompi_list_get_end(&x),
&list, item, ompi_list_get_end(&list));
tmp_size_1 = ompi_list_get_size(&list);
tmp_size_2 = ompi_list_get_size(&x);
if (tmp_size_1 != i) {
test_failure(" error in splice (size of list)");
} else if (tmp_size_2 != list_size - tmp_size_1) {
test_failure(" error in splice (size of x)");
} else {
test_success();
}
ompi_list_join(&list, ompi_list_get_end(&list), &x);
tmp_size_1 = ompi_list_get_size(&list);
tmp_size_2 = ompi_list_get_size(&x);
if (tmp_size_1 != list_size) {
test_failure(" error in join (size of list)");
} else if (tmp_size_2 != 0) {
test_failure(" error in join (size of x)");
} else {
test_success();
}
return test_finalize();
}