Main Page
Modules
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
modules
common
src
include
citrusleaf
src/include/citrusleaf/cf_ll.h
Go to the documentation of this file.
1
/******************************************************************************
2
* Copyright 2008-2013 by Aerospike.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a copy
5
* of this software and associated documentation files (the "Software"), to
6
* deal in the Software without restriction, including without limitation the
7
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
* sell copies of the Software, and to permit persons to whom the Software is
9
* furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
* IN THE SOFTWARE.
21
*****************************************************************************/
22
#pragma once
23
24
/*
25
* SYNOPSIS
26
* LinkedList
27
* Sometimes the answer is a doubly linked list. It's not that frequent, but
28
* all the corner cases in a double linked list can be annoying.
29
*
30
* the current use pattern is the caller creates a structure that starts with a 'cf_ll_element',
31
* ie, can be cast to a cf_ll_element. The caller allocates and frees the memory.
32
* (There are far cooler ways to do this, so if you want to improve this, go ahead!
33
*
34
*/
35
36
#include <pthread.h>
37
#include <inttypes.h>
38
#include <citrusleaf/cf_types.h>
39
40
#ifdef __cplusplus
41
extern
"C"
{
42
#endif
43
44
/******************************************************************************
45
* CONSTANTS
46
******************************************************************************/
47
48
#define CF_LL_REDUCE_DELETE (1)
49
#define CF_LL_REDUCE_INSERT (2)
50
#define CF_LL_REDUCE_MATCHED (3)
51
#define CF_LL_REDUCE_NOT_MATCHED (4)
52
/******************************************************************************
53
* TYPES
54
******************************************************************************/
55
56
typedef
struct
cf_ll_s
cf_ll;
57
typedef
struct
cf_ll_element_s
cf_ll_element;
58
typedef
struct
cf_ll_iterator_s
cf_ll_iterator;
59
typedef
int (*
cf_ll_reduce_fn
) (cf_ll_element * e,
void
*udata);
60
typedef
void (*
cf_ll_destructor
) (cf_ll_element * e);
61
62
/**
63
* cf_ll_element
64
* The element that must be included in structures
65
* This element should be the FIRST element in the structure where it is being included
66
*/
67
struct
cf_ll_element_s
{
68
cf_ll_element *
next
;
69
cf_ll_element *
prev
;
70
};
71
72
/**
73
* cf_ll_iterator
74
* the linked list iterator
75
*/
76
struct
cf_ll_iterator_s
{
77
cf_ll_element *
next
;
78
bool
forward
;
79
};
80
/**
81
* cf_ll
82
* the linked list container
83
*/
84
struct
cf_ll_s
{
85
cf_ll_element *
head
;
86
cf_ll_element *
tail
;
87
cf_ll_destructor
destroy_fn
;
88
uint32_t
sz
;
89
bool
uselock
;
90
#ifdef EXTERNAL_LOCKS
91
void
*
LOCK
;
92
#else
93
pthread_mutex_t
LOCK
;
94
#endif //EXTERNAL_LOCKS
95
};
96
97
/******************************************************************************
98
* INLINE FUNCTIONS
99
******************************************************************************/
100
101
static
inline
cf_ll_element *
cf_ll_get_head
(cf_ll *ll) {
102
return
(ll->head);
103
}
104
105
static
inline
cf_ll_element *
cf_ll_get_tail
(cf_ll *ll) {
106
return
(ll->tail);
107
}
108
109
static
inline
cf_ll_element *
cf_ll_get_next
(cf_ll_element *e) {
110
return
(e->next);
111
}
112
113
static
inline
cf_ll_element *
cf_ll_get_prev
(cf_ll_element *e) {
114
return
(e->prev);
115
}
116
117
/******************************************************************************
118
* FUNCTIONS
119
******************************************************************************/
120
121
/**
122
* Insert to head
123
*/
124
void
cf_ll_prepend
(cf_ll *ll, cf_ll_element *e );
125
126
/**
127
* Insert to tail
128
*/
129
void
cf_ll_append
(cf_ll *ll, cf_ll_element *e );
130
131
/**
132
* Insert after element !! warning! consider threadsafety before using this call!
133
*/
134
void
cf_ll_insert_after
(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
135
136
/**
137
* Insert before element !! warning! consider threadsafey before using this call!
138
*/
139
void
cf_ll_insert_before
(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
140
141
/**
142
* delete element - the real joy of a doubly linked list
143
* If a destructor function has been set, call it as well
144
*/
145
void
cf_ll_delete
(cf_ll *ll, cf_ll_element *e );
146
147
uint32_t
cf_ll_size
(cf_ll *ll);
148
/*
149
* Create a iterator for linked list. Will move from head to tail
150
* if forward is true else from tail to head
151
*/
152
cf_ll_iterator *
cf_ll_getIterator
(cf_ll * ll,
bool
forward);
153
154
/*
155
* Get next element of linked list pointed by iterator
156
*/
157
cf_ll_element *
cf_ll_getNext
(cf_ll_iterator *iter);
158
159
/*
160
* Release iterator
161
*/
162
void
cf_ll_releaseIterator
(cf_ll_iterator *iter);
163
164
/*
165
* Search an element in the linked list.
166
*/
167
cf_ll_element *
cf_ll_search
(cf_ll *ll, cf_ll_element *e,
bool
forward,
cf_ll_reduce_fn
fn);
168
169
/*
170
* Get the linked list element through indexing
171
*/
172
cf_ll_element *
cf_ll_index
(cf_ll *ll,
int
index);
173
/**
174
* The way these reduces work:
175
* ** If you're reducing and you want to delete this element, return CF_LL_REDUCE_DELETE
176
* and it'll be removed from the list - but iteration will not halt
177
* ** If you return a negative value, the reduction will terminate immediatly and that
178
* return value will be passed to the reducer
179
* ** The 'forward' parameter specifies whether you want to traverse from front to back,
180
* pass in 'false' to go tail-to-head
181
*/
182
int
cf_ll_reduce
( cf_ll *ll,
bool
forward,
cf_ll_reduce_fn
fn,
void
*udata);
183
184
/**
185
* Insert-before
186
* Sometimes you want to iterate a list, and insert before a certain element.
187
* Common when you're trying to keep a sorted list and you have some knowledge
188
* that either the list is short, or you're doing inserts of a particular pattern
189
* so that a sorted-table is not the right answer.
190
*
191
* Similar to the reduce function: if you want to bail out of the insert, return a negative
192
* If you want to insert "here", return the special code
193
* At the end of the list, you will be passed a null element (thus meaning you'll always
194
* be called at least once)
195
*/
196
int
cf_ll_insert_reduce
(cf_ll *ll, cf_ll_element *e,
bool
forward,
cf_ll_reduce_fn
fn,
void
*udata);
197
198
/**
199
* Call this function on a head structure to initialize it to empty
200
* Call with whether you want a locked version of a lockfree version
201
* if you're handling your own locks
202
*
203
* If you're using a standard delete methodology, then don't need a destructor function,
204
* and can leave it blank. But if you're using the reduce / delete pattern, then
205
* there's not an easy way for the application-level delete to occur, because you can't
206
* free the structure first then call delete. (you could insert the element on a queue,
207
* but it would have to carefully be a reference counted object, and then you'd still
208
* need the linked-list-reduceor to decrement the linked list....)
209
* In that case, you need to have a destructor
210
* function that gets fired every time a removal from the list occurs. even on explicit
211
* deletes it's called, just to be fancy.
212
*
213
* Note that when the destructor is called, the lock for the linked list is held
214
* (if you've allocated the linked list with a lock)
215
*/
216
int
cf_ll_init
(cf_ll *ll,
cf_ll_destructor
destroy_fn,
bool
uselock);
217
218
/******************************************************************************/
219
220
#ifdef __cplusplus
221
}
// end extern "C"
222
#endif