* 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.
Этот коммит содержится в:
родитель
08de49cc4a
Коммит
c5ebf49f41
@ -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();
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user