lib: Impelement the *_del list API.

The new list api did not implement the `*_del` endpoint as
it was described in the docs here:

http://docs.frrouting.org/projects/dev-guide/en/latest/lists.html#c.Z_del

This patch implements the endpoints to return the object deleted if
found, otherwise NULL for all but the atomic lists.

The atomic list `*_del` code is marked as TODO and will remain undefined
for now.

Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
This commit is contained in:
Stephen Worley 2019-07-23 12:23:25 -04:00
parent 2e6f2d6bc7
commit da098d78bb
5 changed files with 46 additions and 24 deletions

View File

@ -135,8 +135,10 @@ macro_inline void prefix ## _add_tail(struct prefix##_head *h, type *item) \
macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \ macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \
_Atomic atomptr_t *hint) \ _Atomic atomptr_t *hint) \
{ atomlist_del_hint(&h->ah, &item->field.ai, hint); } \ { atomlist_del_hint(&h->ah, &item->field.ai, hint); } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ atomlist_del_hint(&h->ah, &item->field.ai, NULL); } \ { atomlist_del_hint(&h->ah, &item->field.ai, NULL); \
/* TODO: Return NULL if not found */ \
return item; } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ char *p = (char *)atomlist_pop(&h->ah); \ { char *p = (char *)atomlist_pop(&h->ah); \
return p ? (type *)(p - offsetof(type, field)) : NULL; } \ return p ? (type *)(p - offsetof(type, field)) : NULL; } \
@ -273,9 +275,11 @@ macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \
{ \ { \
atomsort_del_hint(&h->ah, &item->field.ai, hint); \ atomsort_del_hint(&h->ah, &item->field.ai, hint); \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
atomsort_del_hint(&h->ah, &item->field.ai, NULL); \ atomsort_del_hint(&h->ah, &item->field.ai, NULL); \
/* TODO: Return NULL if not found */ \
return item; \
} \ } \
macro_inline size_t prefix ## _count(struct prefix##_head *h) \ macro_inline size_t prefix ## _count(struct prefix##_head *h) \
{ \ { \

View File

@ -333,9 +333,10 @@ color:
return (old); return (old);
} }
void typed_rb_remove(struct rbt_tree *rbt, struct rb_entry *rbe) struct typed_rb_entry *typed_rb_remove(struct rbt_tree *rbt,
struct rb_entry *rbe)
{ {
rbe_remove(rbt, rbe); return rbe_remove(rbt, rbe);
} }
struct typed_rb_entry *typed_rb_insert(struct rbt_tree *rbt, struct typed_rb_entry *typed_rb_insert(struct rbt_tree *rbt,

View File

@ -43,7 +43,8 @@ struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *,
int (*cmpfn)( int (*cmpfn)(
const struct typed_rb_entry *a, const struct typed_rb_entry *a,
const struct typed_rb_entry *b)); const struct typed_rb_entry *b));
void typed_rb_remove(struct typed_rb_root *, struct typed_rb_entry *rbe); struct typed_rb_entry *typed_rb_remove(struct typed_rb_root *,
struct typed_rb_entry *rbe);
struct typed_rb_entry *typed_rb_find(struct typed_rb_root *, struct typed_rb_entry *typed_rb_find(struct typed_rb_root *,
const struct typed_rb_entry *rbe, const struct typed_rb_entry *rbe,
int (*cmpfn)( int (*cmpfn)(
@ -99,9 +100,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
re = typed_rb_find_lt(&h->rr, &item->field.re, cmpfn_nuq); \ re = typed_rb_find_lt(&h->rr, &item->field.re, cmpfn_nuq); \
return container_of_null(re, type, field.re); \ return container_of_null(re, type, field.re); \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
typed_rb_remove(&h->rr, &item->field.re); \ struct typed_rb_entry *re; \
re = typed_rb_remove(&h->rr, &item->field.re); \
return container_of_null(re, type, field.re); \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \

View File

@ -341,13 +341,14 @@ struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head,
return best; return best;
} }
void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item, struct sskip_item *typesafe_skiplist_del(
int (*cmpfn)(const struct sskip_item *a, struct sskip_head *head, struct sskip_item *item,
const struct sskip_item *b)) int (*cmpfn)(const struct sskip_item *a, const struct sskip_item *b))
{ {
size_t level = SKIPLIST_MAXDEPTH; size_t level = SKIPLIST_MAXDEPTH;
struct sskip_item *prev = &head->hitem, *next; struct sskip_item *prev = &head->hitem, *next;
int cmpval; int cmpval;
bool found = false;
while (level) { while (level) {
next = sl_level_get(prev, level - 1); next = sl_level_get(prev, level - 1);
@ -359,6 +360,7 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
sl_level_set(prev, level - 1, sl_level_set(prev, level - 1,
sl_level_get(item, level - 1)); sl_level_get(item, level - 1));
level--; level--;
found = true;
continue; continue;
} }
cmpval = cmpfn(next, item); cmpval = cmpfn(next, item);
@ -369,6 +371,9 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
level--; level--;
} }
if (!found)
return NULL;
/* TBD: assert when trying to remove non-existing item? */ /* TBD: assert when trying to remove non-existing item? */
head->count--; head->count--;
@ -379,6 +384,8 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item,
XFREE(MTYPE_SKIPLIST_OFLOW, oflow); XFREE(MTYPE_SKIPLIST_OFLOW, oflow);
} }
memset(item, 0, sizeof(*item)); memset(item, 0, sizeof(*item));
return item;
} }
struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head) struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head)

View File

@ -109,17 +109,18 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
typesafe_list_add(&h->sh, nextp, &item->field.si); \ typesafe_list_add(&h->sh, nextp, &item->field.si); \
} \ } \
/* TODO: del_hint */ \ /* TODO: del_hint */ \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
struct slist_item **iter = &h->sh.first; \ struct slist_item **iter = &h->sh.first; \
while (*iter && *iter != &item->field.si) \ while (*iter && *iter != &item->field.si) \
iter = &(*iter)->next; \ iter = &(*iter)->next; \
if (!*iter) \ if (!*iter) \
return; \ return NULL; \
h->sh.count--; \ h->sh.count--; \
*iter = item->field.si.next; \ *iter = item->field.si.next; \
if (!item->field.si.next) \ if (!item->field.si.next) \
h->sh.last_next = iter; \ h->sh.last_next = iter; \
return item; \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -212,13 +213,14 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
prev = after ? &after->field.di : &h->dh.hitem; \ prev = after ? &after->field.di : &h->dh.hitem; \
typesafe_dlist_add(&h->dh, prev, &item->field.di); \ typesafe_dlist_add(&h->dh, prev, &item->field.di); \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
struct dlist_item *ditem = &item->field.di; \ struct dlist_item *ditem = &item->field.di; \
ditem->prev->next = ditem->next; \ ditem->prev->next = ditem->next; \
ditem->next->prev = ditem->prev; \ ditem->next->prev = ditem->prev; \
h->dh.count--; \ h->dh.count--; \
ditem->prev = ditem->next = NULL; \ ditem->prev = ditem->next = NULL; \
return item; \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -308,7 +310,7 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
h->hh.count++; \ h->hh.count++; \
return NULL; \ return NULL; \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
struct heap_item *other; \ struct heap_item *other; \
uint32_t index = item->field.hi.index; \ uint32_t index = item->field.hi.index; \
@ -321,6 +323,7 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
typesafe_heap_pushdown(&h->hh, index, other, prefix ## __cmp); \ typesafe_heap_pushdown(&h->hh, index, other, prefix ## __cmp); \
if (HEAP_RESIZE_TRESH_DN(h)) \ if (HEAP_RESIZE_TRESH_DN(h)) \
typesafe_heap_resize(&h->hh, false); \ typesafe_heap_resize(&h->hh, false); \
return item; \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -449,15 +452,16 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
return container_of_null(prev, type, field.si); \ return container_of_null(prev, type, field.si); \
} \ } \
/* TODO: del_hint */ \ /* TODO: del_hint */ \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
struct ssort_item **iter = &h->sh.first; \ struct ssort_item **iter = &h->sh.first; \
while (*iter && *iter != &item->field.si) \ while (*iter && *iter != &item->field.si) \
iter = &(*iter)->next; \ iter = &(*iter)->next; \
if (!*iter) \ if (!*iter) \
return; \ return NULL; \
h->sh.count--; \ h->sh.count--; \
*iter = item->field.si.next; \ *iter = item->field.si.next; \
return item; \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -617,10 +621,10 @@ macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \
} \ } \
return NULL; \ return NULL; \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
if (!h->hh.tabshift) \ if (!h->hh.tabshift) \
return; \ return NULL; \
uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \ uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \
struct thash_item **np = &h->hh.entries[hbits]; \ struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \ while (*np && (*np)->hashval < hval) \
@ -628,12 +632,13 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
while (*np && *np != &item->field.hi && (*np)->hashval == hval) \ while (*np && *np != &item->field.hi && (*np)->hashval == hval) \
np = &(*np)->next; \ np = &(*np)->next; \
if (*np != &item->field.hi) \ if (*np != &item->field.hi) \
return; \ return NULL; \
*np = item->field.hi.next; \ *np = item->field.hi.next; \
item->field.hi.next = NULL; \ item->field.hi.next = NULL; \
h->hh.count--; \ h->hh.count--; \
if (HASH_SHRINK_THRESHOLD(h->hh)) \ if (HASH_SHRINK_THRESHOLD(h->hh)) \
typesafe_hash_shrink(&h->hh); \ typesafe_hash_shrink(&h->hh); \
return item; \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -751,9 +756,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
&item->field.si, cmpfn_nuq); \ &item->field.si, cmpfn_nuq); \
return container_of_null(sitem, type, field.si); \ return container_of_null(sitem, type, field.si); \
} \ } \
macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \ { \
typesafe_skiplist_del(&h->sh, &item->field.si, cmpfn_uq); \ struct sskip_item *sitem = typesafe_skiplist_del(&h->sh, \
&item->field.si, cmpfn_uq); \
return container_of_null(sitem, type, field.si); \
} \ } \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \ { \
@ -848,8 +855,8 @@ extern struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head,
const struct sskip_item *item, int (*cmpfn)( const struct sskip_item *item, int (*cmpfn)(
const struct sskip_item *a, const struct sskip_item *a,
const struct sskip_item *b)); const struct sskip_item *b));
extern void typesafe_skiplist_del(struct sskip_head *head, extern struct sskip_item *typesafe_skiplist_del(
struct sskip_item *item, int (*cmpfn)( struct sskip_head *head, struct sskip_item *item, int (*cmpfn)(
const struct sskip_item *a, const struct sskip_item *a,
const struct sskip_item *b)); const struct sskip_item *b));
extern struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head); extern struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head);