Manage the reference count to the items using atomic operations.
Add a field storing a pointer to the list where an item belong. This commit was SVN r5293.
Этот коммит содержится в:
родитель
29f27495de
Коммит
a9ee215d5c
@ -54,13 +54,17 @@ static void ompi_list_item_construct(ompi_list_item_t *item)
|
|||||||
{
|
{
|
||||||
item->ompi_list_next = item->ompi_list_prev = NULL;
|
item->ompi_list_next = item->ompi_list_prev = NULL;
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
ompi_atomic_init(&item->ompi_list_item_lock, OMPI_ATOMIC_UNLOCKED);
|
|
||||||
item->ompi_list_item_refcount = 0;
|
item->ompi_list_item_refcount = 0;
|
||||||
|
item->ompi_list_item_belong_to = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ompi_list_item_destruct(ompi_list_item_t *item)
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -72,24 +76,24 @@ static void ompi_list_item_destruct(ompi_list_item_t *item)
|
|||||||
|
|
||||||
static void ompi_list_construct(ompi_list_t *list)
|
static void ompi_list_construct(ompi_list_t *list)
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
|
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* These refcounts should never be used in assertions because they
|
/* These refcounts should never be used in assertions because they
|
||||||
should never be removed from this list, added to another list,
|
should never be removed from this list, added to another list,
|
||||||
etc. So set them to sentinel values. */
|
etc. So set them to sentinel values. */
|
||||||
|
|
||||||
ompi_atomic_init(&list->ompi_list_head.ompi_list_item_lock,
|
OBJ_CONSTRUCT( &(list->ompi_list_head), ompi_list_item_t );
|
||||||
OMPI_ATOMIC_UNLOCKED);
|
|
||||||
list->ompi_list_head.ompi_list_item_refcount = 1;
|
list->ompi_list_head.ompi_list_item_refcount = 1;
|
||||||
ompi_atomic_init(&list->ompi_list_tail.ompi_list_item_lock,
|
list->ompi_list_head.ompi_list_item_belong_to = list;
|
||||||
OMPI_ATOMIC_UNLOCKED);
|
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_refcount = 1;
|
||||||
|
list->ompi_list_tail.ompi_list_item_belong_to = list;
|
||||||
#endif
|
#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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -143,10 +147,9 @@ bool ompi_list_insert(ompi_list_t *list, ompi_list_item_t *item, long long idx)
|
|||||||
/* Spot check: ensure this item is only on the list that we
|
/* Spot check: ensure this item is only on the list that we
|
||||||
just insertted it into */
|
just insertted it into */
|
||||||
|
|
||||||
ompi_atomic_lock(&item->ompi_list_item_lock);
|
ompi_atomic_add( &(item->ompi_list_item_refcount), 1 );
|
||||||
++item->ompi_list_item_refcount;
|
|
||||||
assert(1 == item->ompi_list_item_refcount);
|
assert(1 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&item->ompi_list_item_lock);
|
item->ompi_list_item_belong_to = list;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +176,13 @@ ompi_list_transfer(ompi_list_item_t *pos, ompi_list_item_t *begin,
|
|||||||
pos->ompi_list_prev = end->ompi_list_prev;
|
pos->ompi_list_prev = end->ompi_list_prev;
|
||||||
end->ompi_list_prev = begin->ompi_list_prev;
|
end->ompi_list_prev = begin->ompi_list_prev;
|
||||||
begin->ompi_list_prev = tmp;
|
begin->ompi_list_prev = tmp;
|
||||||
|
#if OMPI_ENABLE_DEBUG
|
||||||
|
{
|
||||||
|
ompi_list_item_t* item = begin;
|
||||||
|
while( end != item )
|
||||||
|
item->ompi_list_item_belong_to = pos->ompi_list_item_belong_to;
|
||||||
|
}
|
||||||
|
#endif /* OMPI_ENABLE_DEBUG */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,10 +101,10 @@ struct ompi_list_item_t
|
|||||||
/**< Pointer to previous list item */
|
/**< Pointer to previous list item */
|
||||||
|
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/** Atomic lock for debugging (atomic reference counting) */
|
/** Atomic reference count for debugging */
|
||||||
ompi_lock_t ompi_list_item_lock;
|
|
||||||
/** Reference count for debugging */
|
|
||||||
volatile int32_t ompi_list_item_refcount;
|
volatile int32_t ompi_list_item_refcount;
|
||||||
|
/** The list this item belong to */
|
||||||
|
volatile struct ompi_list_t* ompi_list_item_belong_to;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@ -191,13 +191,15 @@ static inline bool ompi_list_is_empty(ompi_list_t* list)
|
|||||||
*/
|
*/
|
||||||
static inline ompi_list_item_t* ompi_list_get_first(ompi_list_t* list)
|
static inline ompi_list_item_t* ompi_list_get_first(ompi_list_t* list)
|
||||||
{
|
{
|
||||||
|
ompi_list_item_t* item = (ompi_list_item_t *)list->ompi_list_head.ompi_list_next;
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* Spot check: ensure that the first item is only on one list */
|
/* Spot check: ensure that the first item is only on one list */
|
||||||
|
|
||||||
assert(1 == list->ompi_list_head.ompi_list_next->ompi_list_item_refcount);
|
assert(1 == item->ompi_list_item_refcount);
|
||||||
|
assert( list == item->ompi_list_item_belong_to );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (ompi_list_item_t *)list->ompi_list_head.ompi_list_next;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,13 +218,15 @@ static inline ompi_list_item_t* ompi_list_get_first(ompi_list_t* list)
|
|||||||
*/
|
*/
|
||||||
static inline ompi_list_item_t* ompi_list_get_last(ompi_list_t* list)
|
static inline ompi_list_item_t* ompi_list_get_last(ompi_list_t* list)
|
||||||
{
|
{
|
||||||
|
ompi_list_item_t* item = (ompi_list_item_t *)list->ompi_list_tail.ompi_list_prev;
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* Spot check: ensure that the last item is only on one list */
|
/* Spot check: ensure that the last item is only on one list */
|
||||||
|
|
||||||
assert(1 == list->ompi_list_tail.ompi_list_prev->ompi_list_item_refcount);
|
assert( 1 == item->ompi_list_item_refcount );
|
||||||
|
assert( list == item->ompi_list_item_belong_to );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (ompi_list_item_t *)list->ompi_list_tail.ompi_list_prev;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -359,12 +363,7 @@ static inline ompi_list_item_t *ompi_list_remove_item
|
|||||||
return (ompi_list_item_t *)NULL;
|
return (ompi_list_item_t *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spot check: ensure this item is only on one list */
|
assert( list == item->ompi_list_item_belong_to );
|
||||||
|
|
||||||
ompi_atomic_lock(&item->ompi_list_item_lock);
|
|
||||||
--item->ompi_list_item_refcount;
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
|
||||||
ompi_atomic_unlock(&item->ompi_list_item_lock);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reset next pointer of previous element */
|
/* reset next pointer of previous element */
|
||||||
@ -378,7 +377,9 @@ static inline ompi_list_item_t *ompi_list_remove_item
|
|||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* Spot check: ensure that this item is still only on one list */
|
/* Spot check: ensure that this item is still only on one list */
|
||||||
|
|
||||||
|
ompi_atomic_sub( &(item->ompi_list_item_refcount), 1 );
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
|
item->ompi_list_item_belong_to = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (ompi_list_item_t *)item->ompi_list_prev;
|
return (ompi_list_item_t *)item->ompi_list_prev;
|
||||||
@ -398,12 +399,28 @@ static inline ompi_list_item_t *ompi_list_remove_item
|
|||||||
* This is an inlined function in compilers that support inlining, so
|
* This is an inlined function in compilers that support inlining, so
|
||||||
* it's usually a cheap operation.
|
* it's usually a cheap operation.
|
||||||
*/
|
*/
|
||||||
static inline void ompi_list_append(ompi_list_t *list, ompi_list_item_t *item)
|
|
||||||
|
#if OMPI_ENABLE_DEBUG
|
||||||
|
#define ompi_list_append(l,i) \
|
||||||
|
_ompi_list_append(l,i,__FILE__,__LINE__)
|
||||||
|
#else
|
||||||
|
#define ompi_list_append(l,i) \
|
||||||
|
_ompi_list_append(l,i)
|
||||||
|
#endif /* OMPI_ENABLE_DEBUG */
|
||||||
|
|
||||||
|
static inline void _ompi_list_append(ompi_list_t *list, ompi_list_item_t *item
|
||||||
|
#if OMPI_ENABLE_DEBUG
|
||||||
|
, char* FILE, int LINENO
|
||||||
|
#endif /* OMPI_ENABLE_DEBUG */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* Spot check: ensure that this item is previously on no lists */
|
/* Spot check: ensure that this item is previously on no lists */
|
||||||
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
|
assert( NULL == item->ompi_list_item_belong_to );
|
||||||
|
item->super.cls_init_file_name = FILE;
|
||||||
|
item->super.cls_init_lineno = LINENO;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* set new element's previous pointer */
|
/* set new element's previous pointer */
|
||||||
@ -425,10 +442,9 @@ static inline void ompi_list_append(ompi_list_t *list, ompi_list_item_t *item)
|
|||||||
/* Spot check: ensure this item is only on the list that we just
|
/* Spot check: ensure this item is only on the list that we just
|
||||||
appended it to */
|
appended it to */
|
||||||
|
|
||||||
ompi_atomic_lock(&item->ompi_list_item_lock);
|
ompi_atomic_add( &(item->ompi_list_item_refcount), 1 );
|
||||||
++item->ompi_list_item_refcount;
|
|
||||||
assert(1 == item->ompi_list_item_refcount);
|
assert(1 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&item->ompi_list_item_lock);
|
item->ompi_list_item_belong_to = list;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,6 +469,7 @@ static inline void ompi_list_prepend(ompi_list_t *list,
|
|||||||
/* Spot check: ensure that this item is previously on no lists */
|
/* Spot check: ensure that this item is previously on no lists */
|
||||||
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
|
assert( NULL == item->ompi_list_item_belong_to );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reset item's next pointer */
|
/* reset item's next pointer */
|
||||||
@ -474,10 +491,9 @@ static inline void ompi_list_prepend(ompi_list_t *list,
|
|||||||
/* Spot check: ensure this item is only on the list that we just
|
/* Spot check: ensure this item is only on the list that we just
|
||||||
prepended it to */
|
prepended it to */
|
||||||
|
|
||||||
ompi_atomic_lock(&item->ompi_list_item_lock);
|
ompi_atomic_add( &(item->ompi_list_item_refcount), 1 );
|
||||||
++item->ompi_list_item_refcount;
|
|
||||||
assert(1 == item->ompi_list_item_refcount);
|
assert(1 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&item->ompi_list_item_lock);
|
item->ompi_list_item_belong_to = list;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,17 +544,16 @@ static inline ompi_list_item_t *ompi_list_remove_first(ompi_list_t *list)
|
|||||||
list->ompi_list_head.ompi_list_next=item->ompi_list_next;
|
list->ompi_list_head.ompi_list_next=item->ompi_list_next;
|
||||||
|
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* debug code */
|
assert( list == item->ompi_list_item_belong_to );
|
||||||
|
item->ompi_list_item_belong_to = NULL;
|
||||||
item->ompi_list_prev=(ompi_list_item_t *)NULL;
|
item->ompi_list_prev=(ompi_list_item_t *)NULL;
|
||||||
item->ompi_list_next=(ompi_list_item_t *)NULL;
|
item->ompi_list_next=(ompi_list_item_t *)NULL;
|
||||||
|
|
||||||
/* Spot check: ensure that the item we're returning is now on no
|
/* Spot check: ensure that the item we're returning is now on no
|
||||||
lists */
|
lists */
|
||||||
|
|
||||||
ompi_atomic_lock(&((ompi_list_item_t*) item)->ompi_list_item_lock);
|
ompi_atomic_sub( &(item->ompi_list_item_refcount), 1 );
|
||||||
--item->ompi_list_item_refcount;
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&((ompi_list_item_t*) item)->ompi_list_item_lock);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (ompi_list_item_t *) item;
|
return (ompi_list_item_t *) item;
|
||||||
@ -591,16 +606,15 @@ static inline ompi_list_item_t *ompi_list_remove_last(ompi_list_t *list)
|
|||||||
list->ompi_list_tail.ompi_list_prev=item->ompi_list_prev;
|
list->ompi_list_tail.ompi_list_prev=item->ompi_list_prev;
|
||||||
|
|
||||||
#if OMPI_ENABLE_DEBUG
|
#if OMPI_ENABLE_DEBUG
|
||||||
/* debug code */
|
assert( list == item->ompi_list_item_belong_to );
|
||||||
item->ompi_list_next = item->ompi_list_prev = (ompi_list_item_t *)NULL;
|
item->ompi_list_next = item->ompi_list_prev = (ompi_list_item_t *)NULL;
|
||||||
|
|
||||||
/* Spot check: ensure that the item we're returning is now on no
|
/* Spot check: ensure that the item we're returning is now on no
|
||||||
lists */
|
lists */
|
||||||
|
|
||||||
ompi_atomic_lock(&((ompi_list_item_t*) item)->ompi_list_item_lock);
|
ompi_atomic_sub( &(item->ompi_list_item_refcount), 1 );
|
||||||
--item->ompi_list_item_refcount;
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&((ompi_list_item_t*) item)->ompi_list_item_lock);
|
item->ompi_list_item_belong_to = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (ompi_list_item_t *) item;
|
return (ompi_list_item_t *) item;
|
||||||
@ -623,6 +637,7 @@ static inline void ompi_list_insert_pos(ompi_list_t *list, ompi_list_item_t *pos
|
|||||||
not on any list */
|
not on any list */
|
||||||
|
|
||||||
assert(0 == item->ompi_list_item_refcount);
|
assert(0 == item->ompi_list_item_refcount);
|
||||||
|
assert( NULL == item->ompi_list_item_belong_to );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* point item at the existing elements */
|
/* point item at the existing elements */
|
||||||
@ -640,10 +655,9 @@ static inline void ompi_list_insert_pos(ompi_list_t *list, ompi_list_item_t *pos
|
|||||||
/* Spot check: double check that this item is only on the list
|
/* Spot check: double check that this item is only on the list
|
||||||
that we just added it to */
|
that we just added it to */
|
||||||
|
|
||||||
ompi_atomic_lock(&item->ompi_list_item_lock);
|
ompi_atomic_add( &(item->ompi_list_item_refcount), 1 );
|
||||||
++item->ompi_list_item_refcount;
|
|
||||||
assert(1 == item->ompi_list_item_refcount);
|
assert(1 == item->ompi_list_item_refcount);
|
||||||
ompi_atomic_unlock(&item->ompi_list_item_lock);
|
item->ompi_list_item_belong_to = list;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user