summaryrefslogtreecommitdiff
path: root/lib/tevent/tevent_util.h
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-02-06 12:25:06 +1100
committerAndrew Tridgell <tridge@samba.org>2010-02-14 18:44:21 +1100
commitccfa40fdc3eb785b71a4d2d59933a2fdc352fb24 (patch)
tree8d44ff04e6df3631512babfb76180f1265c00510 /lib/tevent/tevent_util.h
parent862a17e9ba0aac382a4301d1d60c9d5ea4888959 (diff)
downloadsamba-ccfa40fdc3eb785b71a4d2d59933a2fdc352fb24.tar.gz
samba-ccfa40fdc3eb785b71a4d2d59933a2fdc352fb24.tar.bz2
samba-ccfa40fdc3eb785b71a4d2d59933a2fdc352fb24.zip
util: update three other copies of our dlinklist.h macros
ldb and tevent have their own copies of these macros. This brings them in sync with the master copy of dlinklist.h
Diffstat (limited to 'lib/tevent/tevent_util.h')
-rw-r--r--lib/tevent/tevent_util.h163
1 files changed, 115 insertions, 48 deletions
diff --git a/lib/tevent/tevent_util.h b/lib/tevent/tevent_util.h
index 829cbc2f6e..46a4506dac 100644
--- a/lib/tevent/tevent_util.h
+++ b/lib/tevent/tevent_util.h
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
- Copyright (C) Andrew Tridgell 1998-2005
+ Copyright (C) Andrew Tridgell 1998-2010
Copyright (C) Jelmer Vernooij 2005
This program is free software; you can redistribute it and/or modify
@@ -24,55 +24,94 @@
#ifndef _DLINKLIST_H
#define _DLINKLIST_H
+/*
+ February 2010 - changed list format to have a prev pointer from the
+ list head. This makes DLIST_ADD_END() O(1) even though we only have
+ one list pointer.
+
+ The scheme is as follows:
+
+ 1) with no entries in the list:
+ list_head == NULL
+
+ 2) with 1 entry in the list:
+ list_head->next == NULL
+ list_head->prev == list_head
+
+ 3) with 2 entries in the list:
+ list_head->next == element2
+ list_head->prev == element2
+ element2->prev == list_head
+ element2->next == NULL
+
+ 4) with N entries in the list:
+ list_head->next == element2
+ list_head->prev == elementN
+ elementN->prev == element{N-1}
+ elementN->next == NULL
+
+ This allows us to find the tail of the list by using
+ list_head->prev, which means we can add to the end of the list in
+ O(1) time
-/* hook into the front of the list */
+
+ Note that the 'type' arguments below are no longer needed, but
+ are kept for now to prevent an incompatible argument change
+ */
+
+
+/*
+ add an element at the front of a list
+*/
#define DLIST_ADD(list, p) \
do { \
if (!(list)) { \
- (list) = (p); \
- (p)->next = (p)->prev = NULL; \
+ (p)->prev = (list) = (p); \
+ (p)->next = NULL; \
} else { \
+ (p)->prev = (list)->prev; \
(list)->prev = (p); \
(p)->next = (list); \
- (p)->prev = NULL; \
(list) = (p); \
- }\
+ } \
} while (0)
-/* remove an element from a list - element doesn't have to be in list. */
+/*
+ remove an element from a list
+ Note that the element doesn't have to be in the list. If it
+ isn't then this is a no-op
+*/
#define DLIST_REMOVE(list, p) \
do { \
if ((p) == (list)) { \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
(list) = (p)->next; \
- if (list) (list)->prev = NULL; \
+ } else if ((list) && (p) == (list)->prev) { \
+ (p)->prev->next = NULL; \
+ (list)->prev = (p)->prev; \
} else { \
if ((p)->prev) (p)->prev->next = (p)->next; \
if ((p)->next) (p)->next->prev = (p)->prev; \
} \
- if ((p) != (list)) (p)->next = (p)->prev = NULL; \
+ if ((p) != (list)) (p)->next = (p)->prev = NULL; \
} while (0)
-/* promote an element to the top of the list */
-#define DLIST_PROMOTE(list, p) \
+/*
+ find the head of the list given any element in it.
+ Note that this costs O(N), so you should avoid this macro
+ if at all possible!
+*/
+#define DLIST_HEAD(p, result_head) \
do { \
- DLIST_REMOVE(list, p); \
- DLIST_ADD(list, p); \
-} while (0)
+ (result_head) = (p); \
+ while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
+} while(0)
-/* hook into the end of the list - needs a tmp pointer */
-#define DLIST_ADD_END(list, p, type) \
-do { \
- if (!(list)) { \
- (list) = (p); \
- (p)->next = (p)->prev = NULL; \
- } else { \
- type tmp; \
- for (tmp = (list); tmp->next; tmp = tmp->next) ; \
- tmp->next = (p); \
- (p)->next = NULL; \
- (p)->prev = tmp; \
- } \
-} while (0)
+/* return the last element in the list */
+#define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
+
+/* return the previous element in the list. */
+#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
/* insert 'p' after the given element 'el' in a list. If el is NULL then
this is the same as a DLIST_ADD() */
@@ -81,34 +120,62 @@ do { \
if (!(list) || !(el)) { \
DLIST_ADD(list, p); \
} else { \
- p->prev = el; \
- p->next = el->next; \
- el->next = p; \
- if (p->next) p->next->prev = p; \
+ (p)->prev = (el); \
+ (p)->next = (el)->next; \
+ (el)->next = (p); \
+ if ((p)->next) (p)->next->prev = (p); \
+ if ((list)->prev == (el)) (list)->prev = (p); \
}\
} while (0)
-/* demote an element to the end of the list, needs a tmp pointer */
-#define DLIST_DEMOTE(list, p, tmp) \
+
+/*
+ add to the end of a list.
+ Note that 'type' is ignored
+*/
+#define DLIST_ADD_END(list, p, type) \
+do { \
+ if (!(list)) { \
+ DLIST_ADD(list, p); \
+ } else { \
+ DLIST_ADD_AFTER(list, p, (list)->prev); \
+ } \
+} while (0)
+
+/* promote an element to the from of a list */
+#define DLIST_PROMOTE(list, p) \
+do { \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD(list, p); \
+} while (0)
+
+/*
+ demote an element to the end of a list.
+ Note that 'type' is ignored
+*/
+#define DLIST_DEMOTE(list, p, type) \
do { \
- DLIST_REMOVE(list, p); \
- DLIST_ADD_END(list, p, tmp); \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD_END(list, p, NULL); \
} while (0)
-/* concatenate two lists - putting all elements of the 2nd list at the
- end of the first list */
-#define DLIST_CONCATENATE(list1, list2, type) \
+/*
+ concatenate two lists - putting all elements of the 2nd list at the
+ end of the first list.
+ Note that 'type' is ignored
+*/
+#define DLIST_CONCATENATE(list1, list2, type) \
do { \
- if (!(list1)) { \
- (list1) = (list2); \
- } else { \
- type tmp; \
- for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
- tmp->next = (list2); \
- if (list2) { \
- (list2)->prev = tmp; \
- } \
+ if (!(list1)) { \
+ (list1) = (list2); \
+ } else { \
+ (list1)->prev->next = (list2); \
+ if (list2) { \
+ void *_tmplist = (void *)(list1)->prev; \
+ (list1)->prev = (list2)->prev; \
+ (list2)->prev = _tmplist; \
} \
+ } \
} while (0)
#endif /* _DLINKLIST_H */