root/opal/class/opal_list.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. opal_list_is_empty
  2. opal_list_get_first
  3. opal_list_get_last
  4. opal_list_get_begin
  5. opal_list_get_end
  6. opal_list_get_size
  7. _opal_list_append
  8. opal_list_prepend
  9. opal_list_remove_first
  10. opal_list_remove_last
  11. opal_list_insert_pos

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2006 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2007      Voltaire All rights reserved.
  13  * Copyright (c) 2013      Los Alamos National Security, LLC. All rights
  14  *                         reserved.
  15  * Copyright (c) 2016      Research Organization for Information Science
  16  *                         and Technology (RIST). All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 /**
  24  * @file
  25  *
  26  * The opal_list_t interface is used to provide a generic
  27  * doubly-linked list container for Open MPI.  It was inspired by (but
  28  * is slightly different than) the Stantard Template Library (STL)
  29  * std::list class.  One notable difference from std::list is that
  30  * when an opal_list_t is destroyed, all of the opal_list_item_t
  31  * objects that it contains are orphaned -- they are \em not
  32  * destroyed.
  33  *
  34  * The general idea is that opal_list_item_t objects can be put on an
  35  * opal_list_t.  Hence, you create a new type that derives from
  36  * opal_list_item_t; this new type can then be used with opal_list_t
  37  * containers.
  38  *
  39  * NOTE: opal_list_item_t instances can only be on \em one list at a
  40  * time.  Specifically, if you add an opal_list_item_t to one list,
  41  * and then add it to another list (without first removing it from the
  42  * first list), you will effectively be hosing the first list.  You
  43  * have been warned.
  44  *
  45  * If OPAL_ENABLE_DEBUG is true, a bunch of checks occur, including
  46  * some spot checks for a debugging reference count in an attempt to
  47  * ensure that an opal_list_item_t is only one *one* list at a time.
  48  * Given the highly concurrent nature of this class, these spot checks
  49  * cannot guarantee that an item is only one list at a time.
  50  * Specifically, since it is a desirable attribute of this class to
  51  * not use locks for normal operations, it is possible that two
  52  * threads may [erroneously] modify an opal_list_item_t concurrently.
  53  *
  54  * The only way to guarantee that a debugging reference count is valid
  55  * for the duration of an operation is to lock the item_t during the
  56  * operation.  But this fundamentally changes the desirable attribute
  57  * of this class (i.e., no locks).  So all we can do is spot-check the
  58  * reference count in a bunch of places and check that it is still the
  59  * value that we think it should be.  But this doesn't mean that you
  60  * can run into "unlucky" cases where two threads are concurrently
  61  * modifying an item_t, but all the spot checks still return the
  62  * "right" values.  All we can do is hope that we have enough spot
  63  * checks to statistically drive down the possibility of the unlucky
  64  * cases happening.
  65  */
  66 
  67 #ifndef OPAL_LIST_H
  68 #define OPAL_LIST_H
  69 
  70 #include "opal_config.h"
  71 #include <stdio.h>
  72 #include <stdlib.h>
  73 #include "opal/class/opal_object.h"
  74 
  75 #if OPAL_ENABLE_DEBUG
  76 /* Need atomics for debugging (reference counting) */
  77 #include "opal/sys/atomic.h"
  78 #include "opal/threads/mutex.h"
  79 #endif
  80 
  81 BEGIN_C_DECLS
  82 
  83 /**
  84  * \internal
  85  *
  86  * The class for the list container.
  87  */
  88 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_list_t);
  89 /**
  90  * \internal
  91  *
  92  * Base class for items that are put in list (opal_list_t) containers.
  93  */
  94 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_list_item_t);
  95 
  96 
  97 /**
  98  * \internal
  99  *
 100  * Struct of an opal_list_item_t
 101  */
 102 struct opal_list_item_t
 103 {
 104     opal_object_t super;
 105     /**< Generic parent class for all Open MPI objects */
 106     volatile struct opal_list_item_t * volatile opal_list_next;
 107     /**< Pointer to next list item */
 108     volatile struct opal_list_item_t * volatile opal_list_prev;
 109     /**< Pointer to previous list item */
 110     int32_t item_free;
 111 
 112 #if OPAL_ENABLE_DEBUG
 113     /** Atomic reference count for debugging */
 114     opal_atomic_int32_t opal_list_item_refcount;
 115     /** The list this item belong to */
 116     volatile struct opal_list_t* opal_list_item_belong_to;
 117 #endif
 118 };
 119 /**
 120  * Base type for items that are put in a list (opal_list_t) containers.
 121  */
 122 typedef struct opal_list_item_t opal_list_item_t;
 123 
 124 
 125 /**
 126  * Get the next item in a list.
 127  *
 128  * @param item A list item.
 129  *
 130  * @returns The next item in the list
 131  */
 132 #define opal_list_get_next(item) \
 133     ((item) ? ((opal_list_item_t*) ((opal_list_item_t*)(item))->opal_list_next) : NULL)
 134 
 135 /**
 136  * Get the next item in a list.
 137  *
 138  * @param item A list item.
 139  *
 140  * @returns The next item in the list
 141  */
 142 #define opal_list_get_prev(item) \
 143     ((item) ? ((opal_list_item_t*) ((opal_list_item_t*)(item))->opal_list_prev) : NULL)
 144 
 145 
 146 /**
 147  * \internal
 148  *
 149  * Struct of an opal_list_t
 150  */
 151 struct opal_list_t
 152 {
 153     opal_object_t       super;
 154     /**< Generic parent class for all Open MPI objects */
 155     opal_list_item_t    opal_list_sentinel;
 156     /**< Head and tail item of the list */
 157     volatile size_t     opal_list_length;
 158     /**< Quick reference to the number of items in the list */
 159 };
 160 /**
 161  * List container type.
 162  */
 163 typedef struct opal_list_t opal_list_t;
 164 
 165 /** Cleanly destruct a list
 166  *
 167  * The opal_list_t destructor doesn't release the items on the
 168  * list - so provide two convenience macros that do so and then
 169  * destruct/release the list object itself
 170  *
 171  * @param[in] list List to destruct or release
 172  */
 173 #define OPAL_LIST_DESTRUCT(list)                                  \
 174     do {                                                          \
 175         opal_list_item_t *it;                                     \
 176         if (1 == ((opal_object_t*)(list))->obj_reference_count) { \
 177           while (NULL != (it = opal_list_remove_first(list))) {   \
 178               OBJ_RELEASE(it);                                    \
 179           }                                                       \
 180         }                                                         \
 181         OBJ_DESTRUCT(list);                                       \
 182     } while(0);
 183 
 184 #define OPAL_LIST_RELEASE(list)                                   \
 185     do {                                                          \
 186         opal_list_item_t *it;                                     \
 187         if (1 == ((opal_object_t*)(list))->obj_reference_count) { \
 188           while (NULL != (it = opal_list_remove_first(list))) {   \
 189               OBJ_RELEASE(it);                                    \
 190           }                                                       \
 191         }                                                         \
 192         OBJ_RELEASE(list);                                        \
 193     } while(0);
 194 
 195 
 196 /**
 197  * Loop over a list.
 198  *
 199  * @param[in] item Storage for each item
 200  * @param[in] list List to iterate over
 201  * @param[in] type Type of each list item
 202  *
 203  * This macro provides a simple way to loop over the items in an opal_list_t. It
 204  * is not safe to call opal_list_remove_item from within the loop.
 205  *
 206  * Example Usage:
 207  *
 208  * class_foo_t *foo;
 209  * OPAL_LIST_FOREACH(foo, list, class_foo_t) {
 210  *    do something(foo);
 211  * }
 212  */
 213 #define OPAL_LIST_FOREACH(item, list, type)                             \
 214   for (item = (type *) (list)->opal_list_sentinel.opal_list_next ;      \
 215        item != (type *) &(list)->opal_list_sentinel ;                   \
 216        item = (type *) ((opal_list_item_t *) (item))->opal_list_next)
 217 
 218 /**
 219  * Loop over a list in reverse.
 220  *
 221  * @param[in] item Storage for each item
 222  * @param[in] list List to iterate over
 223  * @param[in] type Type of each list item
 224  *
 225  * This macro provides a simple way to loop over the items in an opal_list_t. It
 226  * is not safe to call opal_list_remove_item from within the loop.
 227  *
 228  * Example Usage:
 229  *
 230  * class_foo_t *foo;
 231  * opal_list_foreach(foo, list, class_foo_t) {
 232  *    do something;
 233  * }
 234  */
 235 #define OPAL_LIST_FOREACH_REV(item, list, type)                         \
 236   for (item = (type *) (list)->opal_list_sentinel.opal_list_prev ;      \
 237        item != (type *) &(list)->opal_list_sentinel ;                   \
 238        item = (type *) ((opal_list_item_t *) (item))->opal_list_prev)
 239 
 240 /**
 241  * Loop over a list in a *safe* way
 242  *
 243  * @param[in] item Storage for each item
 244  * @param[in] next Storage for next item
 245  * @param[in] list List to iterate over
 246  * @param[in] type Type of each list item
 247  *
 248  * This macro provides a simple way to loop over the items in an opal_list_t. It
 249  * is safe to call opal_list_remove_item(list, item) from within the loop.
 250  *
 251  * Example Usage:
 252  *
 253  * class_foo_t *foo, *next;
 254  * opal_list_foreach_safe(foo, next, list, class_foo_t) {
 255  *    do something;
 256  *    opal_list_remove_item (list, (opal_list_item_t *) foo);
 257  * }
 258  */
 259 #define OPAL_LIST_FOREACH_SAFE(item, next, list, type)                  \
 260   for (item = (type *) (list)->opal_list_sentinel.opal_list_next,       \
 261          next = (type *) ((opal_list_item_t *) (item))->opal_list_next ;\
 262        item != (type *) &(list)->opal_list_sentinel ;                   \
 263        item = next, next = (type *) ((opal_list_item_t *) (item))->opal_list_next)
 264 
 265 /**
 266  * Loop over a list in a *safe* way
 267  *
 268  * @param[in] item Storage for each item
 269  * @param[in] next Storage for next item
 270  * @param[in] list List to iterate over
 271  * @param[in] type Type of each list item
 272  *
 273  * This macro provides a simple way to loop over the items in an opal_list_t. If
 274  * is safe to call opal_list_remove_item(list, item) from within the loop.
 275  *
 276  * Example Usage:
 277  *
 278  * class_foo_t *foo, *next;
 279  * opal_list_foreach_safe(foo, next, list, class_foo_t) {
 280  *    do something;
 281  *    opal_list_remove_item (list, (opal_list_item_t *) foo);
 282  * }
 283  */
 284 #define OPAL_LIST_FOREACH_SAFE_REV(item, prev, list, type)              \
 285   for (item = (type *) (list)->opal_list_sentinel.opal_list_prev,       \
 286          prev = (type *) ((opal_list_item_t *) (item))->opal_list_prev ;\
 287        item != (type *) &(list)->opal_list_sentinel ;                   \
 288        item = prev, prev = (type *) ((opal_list_item_t *) (item))->opal_list_prev)
 289 
 290 
 291 /**
 292  * Check for empty list
 293  *
 294  * @param list The list container
 295  *
 296  * @returns true if list's size is 0, false otherwise
 297  *
 298  * This is an O(1) operation.
 299  *
 300  * This is an inlined function in compilers that support inlining,
 301  * so it's usually a cheap operation.
 302  */
 303 static inline bool opal_list_is_empty(opal_list_t* list)
 304 {
 305     return (list->opal_list_sentinel.opal_list_next ==
 306         &(list->opal_list_sentinel) ? true : false);
 307 }
 308 
 309 
 310 /**
 311  * Return the first item on the list (does not remove it).
 312  *
 313  * @param list The list container
 314  *
 315  * @returns A pointer to the first item on the list
 316  *
 317  * This is an O(1) operation to return the first item on the list.  It
 318  * should be compared against the returned value from
 319  * opal_list_get_end() to ensure that the list is not empty.
 320  *
 321  * This is an inlined function in compilers that support inlining, so
 322  * it's usually a cheap operation.
 323  */
 324 static inline opal_list_item_t* opal_list_get_first(opal_list_t* list)
 325 {
 326     opal_list_item_t* item = (opal_list_item_t*)list->opal_list_sentinel.opal_list_next;
 327 #if OPAL_ENABLE_DEBUG
 328     /* Spot check: ensure that the first item is only on one list */
 329 
 330     assert(1 == item->opal_list_item_refcount);
 331     assert( list == item->opal_list_item_belong_to );
 332 #endif
 333 
 334     return item;
 335 }
 336 
 337 /**
 338  * Return the last item on the list (does not remove it).
 339  *
 340  * @param list The list container
 341  *
 342  * @returns A pointer to the last item on the list
 343  *
 344  * This is an O(1) operation to return the last item on the list.  It
 345  * should be compared against the returned value from
 346  * opal_list_get_begin() to ensure that the list is not empty.
 347  *
 348  * This is an inlined function in compilers that support inlining, so
 349  * it's usually a cheap operation.
 350  */
 351 static inline opal_list_item_t* opal_list_get_last(opal_list_t* list)
 352 {
 353     opal_list_item_t* item = (opal_list_item_t *)list->opal_list_sentinel.opal_list_prev;
 354 #if OPAL_ENABLE_DEBUG
 355     /* Spot check: ensure that the last item is only on one list */
 356 
 357     assert( 1 == item->opal_list_item_refcount );
 358     assert( list == item->opal_list_item_belong_to );
 359 #endif
 360 
 361     return item;
 362 }
 363 
 364 /**
 365  * Return the beginning of the list; an invalid list entry suitable
 366  * for comparison only.
 367  *
 368  * @param list The list container
 369  *
 370  * @returns A pointer to the beginning of the list.
 371  *
 372  * This is an O(1) operation to return the beginning of the list.
 373  * Similar to the STL, this is a special invalid list item -- it
 374  * should \em not be used for storage.  It is only suitable for
 375  * comparison to other items in the list to see if they are valid or
 376  * not; it's ususally used when iterating through the items in a list.
 377  *
 378  * This is an inlined function in compilers that support inlining, so
 379  * it's usually a cheap operation.
 380  */
 381 static inline opal_list_item_t* opal_list_get_begin(opal_list_t* list)
 382 {
 383     return &(list->opal_list_sentinel);
 384 }
 385 
 386 /**
 387  * Return the end of the list; an invalid list entry suitable for
 388  * comparison only.
 389  *
 390  * @param list The list container
 391  *
 392  * @returns A pointer to the end of the list.
 393  *
 394  * This is an O(1) operation to return the end of the list.
 395  * Similar to the STL, this is a special invalid list item -- it
 396  * should \em not be used for storage.  It is only suitable for
 397  * comparison to other items in the list to see if they are valid or
 398  * not; it's ususally used when iterating through the items in a list.
 399  *
 400  * This is an inlined function in compilers that support inlining, so
 401  * it's usually a cheap operation.
 402  */
 403 static inline opal_list_item_t* opal_list_get_end(opal_list_t* list)
 404 {
 405     return &(list->opal_list_sentinel);
 406 }
 407 
 408 
 409 /**
 410  * Return the number of items in a list
 411  *
 412  * @param list The list container
 413  *
 414  * @returns The size of the list (size_t)
 415  *
 416  * This is an O(1) lookup to return the size of the list.
 417  *
 418  * This is an inlined function in compilers that support inlining, so
 419  * it's usually a cheap operation.
 420  *
 421  * \warning The size of the list is cached as part of the list.  In
 422  * the future, calling \c opal_list_splice or \c opal_list_join may
 423  * result in this function recomputing the list size, which would be
 424  * an O(N) operation.  If \c opal_list_splice or \c opal_list_join is
 425  * never called on the specified list, this function will always be
 426  * O(1).
 427  */
 428 static inline size_t opal_list_get_size(opal_list_t* list)
 429 {
 430 #if OPAL_ENABLE_DEBUG && 0
 431     /* not sure if we really want this running in devel, as it does
 432      * slow things down.  Wanted for development of splice / join to
 433      * make sure length was reset properly
 434      */
 435     size_t check_len = 0;
 436     opal_list_item_t *item;
 437 
 438     for (item = opal_list_get_first(list) ;
 439          item != opal_list_get_end(list) ;
 440          item = opal_list_get_next(item)) {
 441         check_len++;
 442     }
 443 
 444     if (check_len != list->opal_list_length) {
 445         fprintf(stderr," Error :: opal_list_get_size - opal_list_length does not match actual list length\n");
 446         fflush(stderr);
 447         abort();
 448     }
 449 #endif
 450 
 451     return list->opal_list_length;
 452 }
 453 
 454 
 455 /**
 456  * Remove an item from a list.
 457  *
 458  * @param list The list container
 459  * @param item The item to remove
 460  *
 461  * @returns A pointer to the item on the list previous to the one
 462  * that was removed.
 463  *
 464  * This is an O(1) operation to remove an item from the list.  The
 465  * forward / reverse pointers in the list are updated and the item is
 466  * removed.  The list item that is returned is now "owned" by the
 467  * caller -- they are responsible for OBJ_RELEASE()'ing it.
 468  *
 469  * If debugging is enabled (specifically, if --enable-debug was used
 470  * to configure Open MPI), this is an O(N) operation because it checks
 471  * to see if the item is actually in the list first.
 472  *
 473  * This is an inlined function in compilers that support inlining, so
 474  * it's usually a cheap operation.
 475  */
 476 static inline opal_list_item_t *opal_list_remove_item
 477   (opal_list_t *list, opal_list_item_t *item)
 478 {
 479 #if OPAL_ENABLE_DEBUG
 480     opal_list_item_t *item_ptr;
 481     bool found = false;
 482 
 483     /* check to see that the item is in the list */
 484     for (item_ptr = opal_list_get_first(list);
 485             item_ptr != opal_list_get_end(list);
 486             item_ptr = (opal_list_item_t *)(item_ptr->opal_list_next)) {
 487         if (item_ptr == (opal_list_item_t *) item) {
 488             found = true;
 489             break;
 490         }
 491     }
 492     if (!found) {
 493         fprintf(stderr," Warning :: opal_list_remove_item - the item %p is not on the list %p \n",(void*) item, (void*) list);
 494         fflush(stderr);
 495         return (opal_list_item_t *)NULL;
 496     }
 497 
 498     assert( list == item->opal_list_item_belong_to );
 499 #endif
 500 
 501     /* reset next pointer of previous element */
 502     item->opal_list_prev->opal_list_next=item->opal_list_next;
 503 
 504     /* reset previous pointer of next element */
 505     item->opal_list_next->opal_list_prev=item->opal_list_prev;
 506 
 507     list->opal_list_length--;
 508 
 509 #if OPAL_ENABLE_DEBUG
 510     /* Spot check: ensure that this item is still only on one list */
 511 
 512     OPAL_THREAD_ADD_FETCH32( &(item->opal_list_item_refcount), -1 );
 513     assert(0 == item->opal_list_item_refcount);
 514     item->opal_list_item_belong_to = NULL;
 515 #endif
 516 
 517     return (opal_list_item_t *)item->opal_list_prev;
 518 }
 519 
 520 
 521 /**
 522  * Append an item to the end of the list.
 523  *
 524  * @param list The list container
 525  * @param item The item to append
 526  *
 527  * This is an O(1) operation to append an item to the end of a list.
 528  * The opal_list_item_t is not OBJ_RETAIN()'ed; it is assumed that
 529  * "ownership" of the item is passed from the caller to the list.
 530  *
 531  * This is an inlined function in compilers that support inlining, so
 532  * it's usually a cheap operation.
 533  */
 534 
 535 #if OPAL_ENABLE_DEBUG
 536 #define opal_list_append(l,i) \
 537 _opal_list_append(l,i,__FILE__,__LINE__)
 538 #else
 539 #define opal_list_append(l,i) \
 540 _opal_list_append(l,i)
 541 #endif  /* OPAL_ENABLE_DEBUG */
 542 
 543 static inline void _opal_list_append(opal_list_t *list, opal_list_item_t *item
 544 #if OPAL_ENABLE_DEBUG
 545                                      , const char* FILE_NAME, int LINENO
 546 #endif  /* OPAL_ENABLE_DEBUG */
 547                                      )
 548 {
 549     opal_list_item_t* sentinel = &(list->opal_list_sentinel);
 550 #if OPAL_ENABLE_DEBUG
 551   /* Spot check: ensure that this item is previously on no lists */
 552 
 553   assert(0 == item->opal_list_item_refcount);
 554   assert( NULL == item->opal_list_item_belong_to );
 555   item->super.cls_init_file_name = FILE_NAME;
 556   item->super.cls_init_lineno    = LINENO;
 557 #endif
 558 
 559   /* set new element's previous pointer */
 560   item->opal_list_prev = sentinel->opal_list_prev;
 561 
 562   /* reset previous pointer on current last element */
 563   sentinel->opal_list_prev->opal_list_next = item;
 564 
 565   /* reset new element's next pointer */
 566   item->opal_list_next = sentinel;
 567 
 568   /* reset the list's tail element previous pointer */
 569   sentinel->opal_list_prev = item;
 570 
 571   /* increment list element counter */
 572   list->opal_list_length++;
 573 
 574 #if OPAL_ENABLE_DEBUG
 575   /* Spot check: ensure this item is only on the list that we just
 576      appended it to */
 577 
 578   OPAL_THREAD_ADD_FETCH32( &(item->opal_list_item_refcount), 1 );
 579   assert(1 == item->opal_list_item_refcount);
 580   item->opal_list_item_belong_to = list;
 581 #endif
 582 }
 583 
 584 
 585 /**
 586  * Prepend an item to the beginning of the list.
 587  *
 588  * @param list The list container
 589  * @param item The item to prepend
 590  *
 591  * This is an O(1) operation to prepend an item to the beginning of a
 592  * list.  The opal_list_item_t is not OBJ_RETAIN()'ed; it is assumed
 593  * that "ownership" of the item is passed from the caller to the list.
 594  *
 595  * This is an inlined function in compilers that support inlining, so
 596  * it's usually a cheap operation.
 597  */
 598 static inline void opal_list_prepend(opal_list_t *list,
 599                                      opal_list_item_t *item)
 600 {
 601     opal_list_item_t* sentinel = &(list->opal_list_sentinel);
 602 #if OPAL_ENABLE_DEBUG
 603   /* Spot check: ensure that this item is previously on no lists */
 604 
 605   assert(0 == item->opal_list_item_refcount);
 606   assert( NULL == item->opal_list_item_belong_to );
 607 #endif
 608 
 609   /* reset item's next pointer */
 610   item->opal_list_next = sentinel->opal_list_next;
 611 
 612   /* reset item's previous pointer */
 613   item->opal_list_prev = sentinel;
 614 
 615   /* reset previous first element's previous poiner */
 616   sentinel->opal_list_next->opal_list_prev = item;
 617 
 618   /* reset head's next pointer */
 619   sentinel->opal_list_next = item;
 620 
 621   /* increment list element counter */
 622   list->opal_list_length++;
 623 
 624 #if OPAL_ENABLE_DEBUG
 625   /* Spot check: ensure this item is only on the list that we just
 626      prepended it to */
 627 
 628   OPAL_THREAD_ADD_FETCH32( &(item->opal_list_item_refcount), 1 );
 629   assert(1 == item->opal_list_item_refcount);
 630   item->opal_list_item_belong_to = list;
 631 #endif
 632 }
 633 
 634 
 635 /**
 636  * Remove the first item from the list and return it.
 637  *
 638  * @param list The list container
 639  *
 640  * @returns The first item on the list.  If the list is empty,
 641  * NULL will be returned
 642  *
 643  * This is an O(1) operation to return the first item on the list.  If
 644  * the list is not empty, a pointer to the first item in the list will
 645  * be returned.  Ownership of the item is transferred from the list to
 646  * the caller; no calls to OBJ_RETAIN() or OBJ_RELEASE() are invoked.
 647  *
 648  * This is an inlined function in compilers that support inlining, so
 649  * it's usually a cheap operation.
 650  */
 651 static inline opal_list_item_t *opal_list_remove_first(opal_list_t *list)
 652 {
 653   /*  Removes and returns first item on list.
 654       Caller now owns the item and should release the item
 655       when caller is done with it.
 656   */
 657   opal_list_item_t *item;
 658   if ( 0 == list->opal_list_length ) {
 659     return (opal_list_item_t *)NULL;
 660   }
 661 
 662 #if OPAL_ENABLE_DEBUG
 663   /* Spot check: ensure that the first item is only on this list */
 664 
 665   assert(1 == list->opal_list_sentinel.opal_list_next->opal_list_item_refcount);
 666 #endif
 667 
 668   /* reset list length counter */
 669   list->opal_list_length--;
 670 
 671   /* get pointer to first element on the list */
 672   item = (opal_list_item_t *) list->opal_list_sentinel.opal_list_next;
 673 
 674   /* reset previous pointer of next item on the list */
 675   item->opal_list_next->opal_list_prev = item->opal_list_prev;
 676 
 677   /* reset the head next pointer */
 678   list->opal_list_sentinel.opal_list_next = item->opal_list_next;
 679 
 680 #if OPAL_ENABLE_DEBUG
 681   assert( list == item->opal_list_item_belong_to );
 682   item->opal_list_item_belong_to = NULL;
 683   item->opal_list_prev=(opal_list_item_t *)NULL;
 684   item->opal_list_next=(opal_list_item_t *)NULL;
 685 
 686   /* Spot check: ensure that the item we're returning is now on no
 687      lists */
 688 
 689   OPAL_THREAD_ADD_FETCH32( &item->opal_list_item_refcount, -1 );
 690   assert(0 == item->opal_list_item_refcount);
 691 #endif
 692 
 693   return item;
 694 }
 695 
 696 
 697 /**
 698  * Remove the last item from the list and return it.
 699  *
 700  * @param list The list container
 701  *
 702  * @returns The last item on the list.  If the list is empty,
 703  * NULL will be returned
 704  *
 705  * This is an O(1) operation to return the last item on the list.  If
 706  * the list is not empty, a pointer to the last item in the list will
 707  * be returned.  Ownership of the item is transferred from the list to
 708  * the caller; no calls to OBJ_RETAIN() or OBJ_RELEASE() are invoked.
 709  *
 710  * This is an inlined function in compilers that support inlining, so
 711  * it's usually a cheap operation.
 712  */
 713 static inline opal_list_item_t *opal_list_remove_last(opal_list_t *list)
 714 {
 715   /*  Removes, releases and returns last item on list.
 716       Caller now owns the item and should release the item
 717       when caller is done with it.
 718   */
 719   opal_list_item_t  *item;
 720   if ( 0 == list->opal_list_length ) {
 721       return (opal_list_item_t *)NULL;
 722   }
 723 
 724 #if OPAL_ENABLE_DEBUG
 725   /* Spot check: ensure that the first item is only on this list */
 726 
 727   assert(1 == list->opal_list_sentinel.opal_list_prev->opal_list_item_refcount);
 728 #endif
 729 
 730   /* reset list length counter */
 731   list->opal_list_length--;
 732 
 733   /* get item */
 734   item = (opal_list_item_t *) list->opal_list_sentinel.opal_list_prev;
 735 
 736   /* reset previous pointer on next to last pointer */
 737   item->opal_list_prev->opal_list_next = item->opal_list_next;
 738 
 739   /* reset tail's previous pointer */
 740   list->opal_list_sentinel.opal_list_prev = item->opal_list_prev;
 741 
 742 #if OPAL_ENABLE_DEBUG
 743   assert( list == item->opal_list_item_belong_to );
 744   item->opal_list_next = item->opal_list_prev = (opal_list_item_t *)NULL;
 745 
 746   /* Spot check: ensure that the item we're returning is now on no
 747      lists */
 748 
 749   OPAL_THREAD_ADD_FETCH32(&item->opal_list_item_refcount, -1 );
 750   assert(0 == item->opal_list_item_refcount);
 751   item->opal_list_item_belong_to = NULL;
 752 #endif
 753 
 754   return item;
 755 }
 756 
 757   /**
 758    * Add an item to the list before a given element
 759    *
 760    * @param list The list container
 761    * @param pos List element to insert \c item before
 762    * @param item The item to insert
 763    *
 764    * Inserts \c item before \c pos.  This is an O(1) operation.
 765    */
 766 static inline void opal_list_insert_pos(opal_list_t *list, opal_list_item_t *pos,
 767                                         opal_list_item_t *item)
 768 {
 769 #if OPAL_ENABLE_DEBUG
 770     /* Spot check: ensure that the item we're insertting is currently
 771        not on any list */
 772 
 773     assert(0 == item->opal_list_item_refcount);
 774     assert( NULL == item->opal_list_item_belong_to );
 775 #endif
 776 
 777     /* point item at the existing elements */
 778     item->opal_list_next = pos;
 779     item->opal_list_prev = pos->opal_list_prev;
 780 
 781     /* splice into the list */
 782     pos->opal_list_prev->opal_list_next = item;
 783     pos->opal_list_prev = item;
 784 
 785     /* reset list length counter */
 786     list->opal_list_length++;
 787 
 788 #if OPAL_ENABLE_DEBUG
 789     /* Spot check: double check that this item is only on the list
 790        that we just added it to */
 791 
 792     OPAL_THREAD_ADD_FETCH32( &(item->opal_list_item_refcount), 1 );
 793     assert(1 == item->opal_list_item_refcount);
 794     item->opal_list_item_belong_to = list;
 795 #endif
 796 }
 797 
 798   /**
 799    * Add an item to the list at a specific index location in the list.
 800    *
 801    * @param list The list container
 802    * @param item The item to insert
 803    * @param index Location to add the item
 804    *
 805    * @returns true if insertion succeeded; otherwise false
 806    *
 807    * This is potentially an O(N) operation to traverse down to the
 808    * correct location in the list and add an item.
 809    *
 810    * Example: if idx = 2 and list = item1->item2->item3->item4, then
 811    * after insert, list = item1->item2->item->item3->item4.
 812    *
 813    * If index is greater than the length of the list, no action is
 814    * performed and false is returned.
 815    */
 816   OPAL_DECLSPEC bool opal_list_insert(opal_list_t *list, opal_list_item_t *item,
 817                                       long long idx);
 818 
 819 
 820     /**
 821      * Join a list into another list
 822      *
 823      * @param thislist List container for list being operated on
 824      * @param pos List item in \c thislist marking the position before
 825      *              which items are inserted
 826      * @param xlist List container for list being spliced from
 827      *
 828      * Join a list into another list.  All of the elements of \c xlist
 829      * are inserted before \c pos and removed from \c xlist.
 830      *
 831      * This operation is an O(1) operation.  Both \c thislist and \c
 832      * xlist must be valid list containsers.  \c xlist will be empty
 833      * but valid after the call.  All pointers to \c opal_list_item_t
 834      * containers remain valid, including those that point to elements
 835      * in \c xlist.
 836      */
 837     OPAL_DECLSPEC void opal_list_join(opal_list_t *thislist, opal_list_item_t *pos,
 838                                       opal_list_t *xlist);
 839 
 840 
 841     /**
 842      * Splice a list into another list
 843      *
 844      * @param thislist List container for list being operated on
 845      * @param pos List item in \c thislist marking the position before
 846      *             which items are inserted
 847      * @param xlist List container for list being spliced from
 848      * @param first List item in \c xlist marking the start of elements
 849      *             to be copied into \c thislist
 850      * @param last List item in \c xlist marking the end of elements
 851      * to be copied into \c thislist
 852      *
 853      * Splice a subset of a list into another list.  The \c [first,
 854      * last) elements of \c xlist are moved into \c thislist,
 855      * inserting them before \c pos.  \c pos must be a valid iterator
 856      * in \c thislist and \c [first, last) must be a valid range in \c
 857      * xlist.  \c postition must not be in the range \c [first, last).
 858      * It is, however, valid for \c xlist and \c thislist to be the
 859      * same list.
 860      *
 861      * This is an O(N) operation because the length of both lists must
 862      * be recomputed.
 863      */
 864     OPAL_DECLSPEC void opal_list_splice(opal_list_t *thislist, opal_list_item_t *pos,
 865                                         opal_list_t *xlist, opal_list_item_t *first,
 866                                         opal_list_item_t *last);
 867 
 868     /**
 869      * Comparison function for opal_list_sort(), below.
 870      *
 871      * @param a Pointer to a pointer to an opal_list_item_t.
 872      * Explanation below.
 873      * @param b Pointer to a pointer to an opal_list_item_t.
 874      * Explanation below.
 875      * @retval 1 if \em a is greater than \em b
 876      * @retval 0 if \em a is equal to \em b
 877      * @retval -1 if \em a is less than \em b
 878      *
 879      * This function is invoked by qsort(3) from within
 880      * opal_list_sort().  It is important to understand what
 881      * opal_list_sort() does before invoking qsort, so go read that
 882      * documentation first.
 883      *
 884      * The important thing to realize here is that a and b will be \em
 885      * double pointers to the items that you need to compare.  Here's
 886      * a sample compare function to illustrate this point:
 887      */
 888     typedef int (*opal_list_item_compare_fn_t)(opal_list_item_t **a,
 889                                                opal_list_item_t **b);
 890 
 891     /**
 892      * Sort a list with a provided compare function.
 893      *
 894      * @param list The list to sort
 895      * @param compare Compare function
 896      *
 897      * Put crassly, this function's complexity is O(N) + O(log(N)).
 898      * Its algorithm is:
 899      *
 900      * - remove every item from the list and put the corresponding
 901      *    (opal_list_item_t*)'s in an array
 902      * - call qsort(3) with that array and your compare function
 903      * - re-add every element of the now-sorted array to the list
 904      *
 905      * The resulting list is now ordered.  Note, however, that since
 906      * an array of pointers is sorted, the comparison function must do
 907      * a double de-reference to get to the actual opal_list_item_t (or
 908      * whatever the underlying type is).  See the documentation of
 909      * opal_list_item_compare_fn_t for an example).
 910      */
 911     OPAL_DECLSPEC int opal_list_sort(opal_list_t* list, opal_list_item_compare_fn_t compare);
 912 
 913 END_C_DECLS
 914 
 915 #endif /* OPAL_LIST_H */

/* [<][>][^][v][top][bottom][index][help] */