librdkafka/rdsysqueue.h

334 строки
10 KiB
C

/*
* librd - Rapid Development C library
*
* Copyright (c) 2012-2013, Magnus Edenhill
* Copyright (c) 2012-2013, Andreas Öman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <sys/queue.h>
/*
* Complete missing LIST-ops
*/
#ifndef LIST_FOREACH
#define LIST_FOREACH(var, head, field) \
for ((var) = ((head)->lh_first); \
(var); \
(var) = ((var)->field.le_next))
#endif
#ifndef LIST_EMPTY
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#endif
#ifndef LIST_FIRST
#define LIST_FIRST(head) ((head)->lh_first)
#endif
#ifndef LIST_NEXT
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#endif
#ifndef LIST_INSERT_BEFORE
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (/*CONSTCOND*/0)
#endif
/*
* Complete missing TAILQ-ops
*/
#ifndef TAILQ_INSERT_BEFORE
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#endif
#ifndef TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); (var); (var) = ((var)->field.tqe_next))
#endif
#ifndef TAILQ_FIRST
#define TAILQ_FIRST(head) ((head)->tqh_first)
#endif
#ifndef TAILQ_NEXT
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#endif
#ifndef TAILQ_LAST
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#endif
#ifndef TAILQ_PREV
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#endif
#ifdef TAILQ_FOREACH_SAFE
#ifdef __APPLE__
/* Apple's .._SAFE macro has the temporary variable at the end. */
#undef TAILQ_FOREACH_SAFE
#endif
#endif
#ifndef TAILQ_FOREACH_SAFE
/*
* TAILQ_FOREACH_SAFE() provides a traversal where the current iterated element
* may be freed or unlinked.
* It does not allow freeing or modifying any other element in the list,
* at least not the next element.
*/
#define TAILQ_FOREACH_SAFE(elm,tmpelm,head,field) \
for ((elm) = TAILQ_FIRST(head) ; \
(elm) && ((tmpelm) = TAILQ_NEXT((elm), field), 1) ; \
(elm) = (tmpelm))
#endif
/*
* In Mac OS 10.4 and earlier TAILQ_FOREACH_REVERSE was defined
* differently, redefined it.
*/
#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
#undef TAILQ_FOREACH_REVERSE
#endif
#endif
#ifndef TAILQ_FOREACH_REVERSE
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
(var); \
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
#endif
/**
* Treat the TAILQ as a circular list and return the previous/next entry,
* possibly wrapping to the end/beginning.
*/
#define TAILQ_CIRC_PREV(var, head, headname, field) \
((var) != TAILQ_FIRST(head) ? \
TAILQ_PREV(var, headname, field) : \
TAILQ_LAST(head, headname))
#define TAILQ_CIRC_NEXT(var, head, headname, field) \
((var) != TAILQ_LAST(head, headname) ? \
TAILQ_NEXT(var, field) : \
TAILQ_FIRST(head))
/*
* Some extra functions for LIST manipulation
*/
#define LIST_MOVE(newhead, oldhead, field) do { \
if((oldhead)->lh_first) { \
(oldhead)->lh_first->field.le_prev = &(newhead)->lh_first; \
} \
(newhead)->lh_first = (oldhead)->lh_first; \
} while (0)
#define LIST_INSERT_SORTED(head, elm, field, cmpfunc) do { \
if(LIST_EMPTY(head)) { \
LIST_INSERT_HEAD(head, elm, field); \
} else { \
typeof(elm) _tmp; \
LIST_FOREACH(_tmp,head,field) { \
if(cmpfunc(elm,_tmp) <= 0) { \
LIST_INSERT_BEFORE(_tmp,elm,field); \
break; \
} \
if(!LIST_NEXT(_tmp,field)) { \
LIST_INSERT_AFTER(_tmp,elm,field); \
break; \
} \
} \
} \
} while(0)
#ifndef TAILQ_INSERT_SORTED
#define TAILQ_INSERT_SORTED(head, elm, field, cmpfunc) do { \
if(TAILQ_FIRST(head) == NULL) { \
TAILQ_INSERT_HEAD(head, elm, field); \
} else { \
typeof(elm) _tmp; \
TAILQ_FOREACH(_tmp,head,field) { \
if(cmpfunc(elm,_tmp) <= 0) { \
TAILQ_INSERT_BEFORE(_tmp,elm,field); \
break; \
} \
if(!TAILQ_NEXT(_tmp,field)) { \
TAILQ_INSERT_AFTER(head,_tmp,elm,field); \
break; \
} \
} \
} \
} while(0)
#endif
#define TAILQ_MOVE(newhead, oldhead, field) do { \
if(TAILQ_FIRST(oldhead)) { \
TAILQ_FIRST(oldhead)->field.tqe_prev = &(newhead)->tqh_first; \
} \
(newhead)->tqh_first = (oldhead)->tqh_first; \
(newhead)->tqh_last = (oldhead)->tqh_last; \
} while (/*CONSTCOND*/0)
#ifndef TAILQ_CONCAT
#define TAILQ_CONCAT(dhead, shead, field) do { \
if (!TAILQ_EMPTY(shead)) { \
*(dhead)->tqh_last = (shead)->tqh_first; \
(shead)->tqh_first->field.tqe_prev = \
(dhead)->tqh_last; \
(dhead)->tqh_last = (shead)->tqh_last; \
TAILQ_INIT((shead)); \
} \
} while (0)
#endif
#ifndef SIMPLEQ_HEAD
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; \
struct type **sqh_last; \
}
#endif
#ifndef SIMPLEQ_ENTRY
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; \
}
#endif
#ifndef SIMPLEQ_FIRST
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#endif
#ifndef SIMPLEQ_REMOVE_HEAD
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#endif
#ifndef SIMPLEQ_INSERT_TAIL
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#endif
#ifndef SIMPLEQ_INIT
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#endif
#ifndef SIMPLEQ_INSERT_HEAD
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#endif
#ifndef SIMPLEQ_FOREACH
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#endif
#ifndef SIMPLEQ_INSERT_AFTER
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#endif
#ifndef SIMPLEQ_END
#define SIMPLEQ_END(head) NULL
#endif
#ifndef SIMPLEQ_NEXT
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#endif
#ifndef SIMPLEQ_HEAD_INITIALIZER
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#endif
#ifndef SIMPLEQ_EMPTY
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#endif