lqueue: Allow a queueu to be initialized from an existing back element
authorDavid Gibson <david@gibson.dropbear.id.au>
Sat, 13 Jun 2015 14:24:57 +0000 (00:24 +1000)
committerDavid Gibson <david@gibson.dropbear.id.au>
Sat, 13 Jun 2015 14:25:24 +0000 (00:25 +1000)
There are occasional cases where you might construct a valid queue, and
retain a direct pointer to the back element, but not the struct lqueue
used to build it.

This patch adds a new lqueue_init_from_back() macro to reconstruct a valid
struct lqueue from the element pointer for cases like this.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
ccan/lqueue/lqueue.h

index 15d242ef127349f06882c697d201d8d01ff2f265..1af5847fe24bb6d448f324afc32ef75547cd3f5c 100644 (file)
@@ -50,6 +50,33 @@ struct lqueue {
 #define LQUEUE(name) \
        struct lqueue name = { NULL, }
 
+/**
+ * lqueue_init_from_back - initialize a queue with a specific back element
+ * @s: the lqueue to initialize
+ * @e: pointer to the back element of the new queue
+ * @member: member of the element containing the lqueue_link
+ *
+ * USE WITH CAUTION: This is for handling unusual cases where you have
+ * a pointer to an element in a previously constructed queue but can't
+ * conveniently pass around a normal struct lqueue.  Usually you
+ * should use lqueue_init().
+ *
+ * Example:
+ *     LQUEUE(queue1);
+ *     struct lqueue queue2;
+ *     struct element {
+ *             int value;
+ *             struct lqueue_link link;
+ *     } el;
+ *
+ *     lqueue_enqueue(&queue1, &el, link);
+ *
+ *     lqueue_init_from_back(&queue2,
+ *                           lqueue_back(&queue1, struct element, link), link);
+ */
+#define lqueue_init_from_back(s, e, member) \
+       (lqueue_init_((s), &(e)->member))
+
 /**
  * lqueue_init - initialize a queue
  * @h: the lqueue to set to an empty queue
@@ -58,9 +85,11 @@ struct lqueue {
  *     struct lqueue *qp = malloc(sizeof(*qp));
  *     lqueue_init(qp);
  */
-static inline void lqueue_init(struct lqueue *q)
+#define lqueue_init(s) \
+       (lqueue_init_((s), NULL))
+static inline void lqueue_init_(struct lqueue *q, struct lqueue_link *back)
 {
-       q->back = NULL;
+       q->back = back;
 }
 
 /**