hce-node application  1.4.3
HCE Hierarchical Cluster Engine node application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cf_ll.h
Go to the documentation of this file.
1 /*
2  * Citrusleaf Foundation
3  * include/ll.h - linked list functionality
4  *
5  * Copyright 2008 by Citrusleaf. All rights reserved.
6  * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE. THE COPYRIGHT NOTICE
7  * ABOVE DOES NOT EVIDENCE ANY ACTUAL OR INTENDED PUBLICATION.
8  */
9 #pragma once
10 
11 #include <pthread.h>
12 #include <stdint.h>
13 
15 
16 /* SYNOPSIS
17  * LinkedList
18  * Sometimes the answer is a doubly linked list. It's not that frequent, but
19  * all the corner cases in a double linked list can be annoying.
20  *
21  * the current use pattern is the caller creates a structure that starts with a 'cf_ll_element',
22  * ie, can be cast to a cf_ll_element. The caller allocates and frees the memory.
23  * (There are far cooler ways to do this, so if you want to improve this, go ahead!
24  *
25  */
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 //
32 // Callbacks in use!
33 // These function expose functional programming paradigms across linked
34 // lists
35 
36 
37 #define CF_LL_REDUCE_DELETE (1)
38 #define CF_LL_REDUCE_INSERT (2)
39 
40 struct cf_ll_element_s;
41 typedef int (*cf_ll_reduce_fn) (struct cf_ll_element_s *e, void *udata);
42 typedef void (*cf_ll_destructor) (struct cf_ll_element_s *e);
43 
44 
45 /* cf_ll_element
46  * The element that must be included in structures
47  * This element should be the FIRST element in the structure where it is being included
48  */
49 
50 typedef struct cf_ll_element_s {
54 
55 /* cf_ll
56 ** the linked list container
57 */
58 
59 
60 
61 typedef struct cf_ll_s {
65  uint32_t sz;
66  bool uselock;
67 #ifdef EXTERNAL_LOCKS
68  void *LOCK;
69 #else
70  pthread_mutex_t LOCK;
71 #endif //EXTERNAL_LOCKS
72 } cf_ll;
73 
74 // Insert to head
75 extern void cf_ll_prepend(cf_ll *ll, cf_ll_element *e );
76 // Insert to tail
77 extern void cf_ll_append(cf_ll *ll, cf_ll_element *e );
78 
79 // Insert after element !! warning! consider threadsafety before using this call!
80 extern void cf_ll_insert_after(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
81 // Insert before element !! warning! consider threadsafey before using this call!
82 extern void cf_ll_insert_before(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
83 
84 static inline cf_ll_element *cf_ll_get_head(cf_ll *ll)
85 {
86  return(ll->head);
87 }
88 
89 static inline cf_ll_element *cf_ll_get_tail(cf_ll *ll)
90 {
91  return(ll->tail);
92 }
93 
94 static inline cf_ll_element *cf_ll_get_next(cf_ll_element *e)
95 {
96  return(e->next);
97 }
98 
99 static inline cf_ll_element *cf_ll_get_prev(cf_ll_element *e)
100 {
101  return(e->prev);
102 }
103 
104 // delete element - the real joy of a doubly linked list
105 // If a destructor function has been set, call it as well
106 extern void cf_ll_delete(cf_ll *ll, cf_ll_element *e );
107 
108 extern uint32_t cf_ll_size(cf_ll *ll);
109 
110 //
111 // The way these reduces work:
112 // ** If you're reducing and you want to delete this element, return CF_LL_REDUCE_DELETE
113 // and it'll be removed from the list - but iteration will not halt
114 // ** If you return a negative value, the reduction will terminate immediatly and that
115 // return value will be passed to the reducer
116 // ** The 'forward' parameter specifies whether you want to traverse from front to back,
117 // pass in 'false' to go tail-to-head
118 
119 
120 extern int cf_ll_reduce( cf_ll *ll, bool forward, cf_ll_reduce_fn fn, void *udata);
121 
122 //
123 // Insert-before
124 // Sometimes you want to iterate a list, and insert before a certain element.
125 // Common when you're trying to keep a sorted list and you have some knowledge
126 // that either the list is short, or you're doing inserts of a particular pattern
127 // so that a sorted-table is not the right answer.
128 //
129 // Similar to the reduce function: if you want to bail out of the insert, return a negative
130 // If you want to insert "here", return the special code
131 // At the end of the list, you will be passed a null element (thus meaning you'll always
132 // be called at least once)
133 
134 
135 extern int cf_ll_insert_reduce(cf_ll *ll, cf_ll_element *e, bool forward, cf_ll_reduce_fn fn, void *udata);
136 
137 
138 /* Call this function on a head structure to initialize it to empty
139 ** Call with whether you want a locked version of a lockfree version
140 ** if you're handling your own locks
141 */
142 
143 /*
144 ** If you're using a standard delete methodology, then don't need a destructor function,
145 ** and can leave it blank. But if you're using the reduce / delete pattern, then
146 ** there's not an easy way for the application-level delete to occur, because you can't
147 ** free the structure first then call delete. (you could insert the element on a queue,
148 ** but it would have to carefully be a reference counted object, and then you'd still
149 ** need the linked-list-reduceor to decrement the linked list....)
150 ** In that case, you need to have a destructor
151 ** function that gets fired every time a removal from the list occurs. even on explicit
152 ** deletes it's called, just to be fancy.
153 **
154 ** Note that when the destructor is called, the lock for the linked list is held
155 ** (if you've allocated the linked list with a lock)
156 */
157 
158 
159 extern int cf_ll_init(cf_ll *ll, cf_ll_destructor destroy_fn, bool uselock);
160 
161 #ifdef __cplusplus
162 } // end extern "C"
163 #endif
164 
165