diff options
Diffstat (limited to 'lib/queue.c')
-rw-r--r-- | lib/queue.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/queue.c b/lib/queue.c new file mode 100644 index 000000000..2e4c7ca62 --- /dev/null +++ b/lib/queue.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2008, 2009 Nicira Networks. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> +#include "queue.h" +#include <assert.h> +#include "compiler.h" +#include "leak-checker.h" +#include "ofpbuf.h" + +static void check_queue(struct ovs_queue *q); + +/* Initializes 'q' as an empty packet queue. */ +void +queue_init(struct ovs_queue *q) +{ + q->n = 0; + q->head = NULL; + q->tail = NULL; +} + +/* Destroys 'q' and all of the packets that it contains. */ +void +queue_destroy(struct ovs_queue *q) +{ + struct ofpbuf *cur, *next; + for (cur = q->head; cur != NULL; cur = next) { + next = cur->next; + ofpbuf_delete(cur); + } +} + +/* Removes and destroys all of the packets in 'q', rendering it empty. */ +void +queue_clear(struct ovs_queue *q) +{ + queue_destroy(q); + queue_init(q); +} + +/* Advances the first packet in 'q' from 'q->head' to 'next', which should be + * the second packet in the queue. + * + * The odd, unsafe interface here allows the first packet in the queue to be + * passed to a function for possible consumption (and destruction) and only + * dropped from the queue if that function actually accepts it. */ +void +queue_advance_head(struct ovs_queue *q, struct ofpbuf *next) +{ + assert(q->n); + assert(q->head); + q->head = next; + if (q->head == NULL) { + q->tail = NULL; + } + q->n--; +} + +/* Appends 'b' to the tail of 'q'. */ +void +queue_push_tail(struct ovs_queue *q, struct ofpbuf *b) +{ + check_queue(q); + leak_checker_claim(b); + + b->next = NULL; + if (q->n++) { + q->tail->next = b; + } else { + q->head = b; + } + q->tail = b; + + check_queue(q); +} + +/* Removes the first buffer from 'q', which must not be empty, and returns + * it. The caller must free the buffer (with ofpbuf_delete()) when it is no + * longer needed. */ +struct ofpbuf * +queue_pop_head(struct ovs_queue *q) +{ + struct ofpbuf *head = q->head; + queue_advance_head(q, head->next); + return head; +} + +/* Checks the internal integrity of 'q'. For use in debugging. */ +static void +check_queue(struct ovs_queue *q UNUSED) +{ +#if 0 + struct ofpbuf *iter; + size_t n; + + assert(q->n == 0 + ? q->head == NULL && q->tail == NULL + : q->head != NULL && q->tail != NULL); + + n = 0; + for (iter = q->head; iter != NULL; iter = iter->next) { + n++; + assert((iter->next != NULL) == (iter != q->tail)); + } + assert(n == q->n); +#endif +} |