* @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
*
* @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
*
_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
*
(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
*