}
memset(item, 0, sizeof(*item));
}
+
+struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head)
+{
+ size_t level = SKIPLIST_MAXDEPTH;
+ struct sskip_item *prev = &head->hitem, *next, *item;
+
+ item = sl_level_get(prev, 0);
+ if (!item)
+ return NULL;
+
+ do {
+ level--;
+
+ next = sl_level_get(prev, level);
+ if (next != item)
+ continue;
+
+ sl_level_set(prev, level, sl_level_get(item, level));
+ } while (level);
+
+ head->count--;
+
+ if ((uintptr_t)item->next[SKIPLIST_OVERFLOW] & 1) {
+ uintptr_t ptrval = (uintptr_t)item->next[SKIPLIST_OVERFLOW];
+ ptrval &= UINTPTR_MAX - 3;
+ struct sskip_overflow *oflow = (struct sskip_overflow *)ptrval;
+ XFREE(MTYPE_SKIPLIST_OFLOW, oflow);
+ }
+ memset(item, 0, sizeof(*item));
+
+ return item;
+}
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
- struct sskip_item *sitem = h->sh.hitem.next[0]; \
- if (!sitem) \
- return NULL; \
- typesafe_skiplist_del(&h->sh, sitem, cmpfn_uq); \
- return container_of(sitem, type, field.si); \
+ struct sskip_item *sitem = typesafe_skiplist_pop(&h->sh); \
+ return container_of_null(sitem, type, field.si); \
} \
macro_pure type *prefix ## _first(struct prefix##_head *h) \
{ \
struct sskip_item *item, int (*cmpfn)(
const struct sskip_item *a,
const struct sskip_item *b));
+extern struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head);
/* this needs to stay at the end because both files include each other.
* the resolved order is typesafe.h before typerb.h