X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvppinfra%2Fllist.h;h=25fb95ff66e9701e74cfd088f1943cd52fb2cd3d;hb=06111a837;hp=1648021681f8b0b74da1558083b9f168f15a4a1c;hpb=b957d807a6003cceecca9002410d66cf7445e9cd;p=vpp.git diff --git a/src/vppinfra/llist.h b/src/vppinfra/llist.h index 1648021681f..25fb95ff66e 100644 --- a/src/vppinfra/llist.h +++ b/src/vppinfra/llist.h @@ -51,6 +51,22 @@ typedef struct clib_llist_anchor * @return pool entry index */ #define clib_llist_entry_index(LP,E) ((E) - (LP)) +/** + * Get prev list entry index + * + * @param E pool entry + * @name list anchor name + * @return previous index + */ +#define clib_llist_prev_index(E,name) _lprev(E,name) +/** + * Get next list entry index + * + * @param E pool entry + * @name list anchor name + * @return next index + */ +#define clib_llist_next_index(E,name) _lnext(E,name) /** * Get next pool entry * @@ -102,7 +118,17 @@ do { \ * @param H list head * @return 1 if sentinel is the only node part of the list, 0 otherwise */ -#define clib_llist_is_empty(LP,name,H) ((H) == clib_llist_next((LP),name,(H))) +#define clib_llist_is_empty(LP,name,H) \ + (clib_llist_entry_index (LP,H) == (H)->name.next) +/** + * Check if element is linked in a list + * + * @param E list element + * @param name list anchor name + */ +#define clib_llist_elt_is_linked(E,name) \ + ((E)->name.next != CLIB_LLIST_INVALID_INDEX \ + && (E)->name.prev != CLIB_LLIST_INVALID_INDEX) /** * Insert entry between previous and next * @@ -175,7 +201,22 @@ do { \ _lprev (_ll_var (N),name) = _lprev (E,name); \ _lnext (E,name) = _lprev (E,name) = CLIB_LLIST_INVALID_INDEX; \ }while (0) - +/** + * Removes and returns the first element in the list. + * + * The element is not freed. It's the responsability of the caller to + * free it. + * + * @param LP linked list pool + * @param name list anchor name + * @param E storage the first entry + * @param H list head entry + */ +#define clib_llist_pop_first(LP,name,E,H) \ +do { \ + E = clib_llist_next (LP,name,H); \ + clib_llist_remove (LP,name,E); \ +} while (0) /** * Splice two lists at a given position * @@ -222,6 +263,28 @@ do { \ (E) = _ll_var (n); \ } \ } while (0) +/** + * Walk list starting at head safe + * + * @param LP linked list pool + * @param name list anchor name + * @param HI head index + * @param EI entry index iterator + * @param body code to be executed + */ +#define clib_llist_foreach_safe(LP,name,H,E,body) \ +do { \ + clib_llist_index_t _ll_var (HI) = clib_llist_entry_index (LP, H); \ + clib_llist_index_t _ll_var (EI), _ll_var (NI); \ + _ll_var (EI) = _lnext ((H),name); \ + while (_ll_var (EI) != _ll_var (HI)) \ + { \ + (E) = pool_elt_at_index (LP, _ll_var (EI)); \ + _ll_var (NI) = _lnext ((E),name); \ + do { body; } while (0); \ + _ll_var (EI) = _ll_var (NI); \ + } \ +} while (0) /** * Walk list starting at head in reverse order *