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
51
/******************************************************************************
52
* TYPES
53
******************************************************************************/
54
55
typedef
struct
cf_ll_s
cf_ll;
56
typedef
struct
cf_ll_element_s
cf_ll_element;
57
58
typedef
int (*
cf_ll_reduce_fn
) (cf_ll_element * e,
void
*udata);
59
typedef
void (*
cf_ll_destructor
) (cf_ll_element * e);
60
61
/**
62
* cf_ll_element
63
* The element that must be included in structures
64
* This element should be the FIRST element in the structure where it is being included
65
*/
66
struct
cf_ll_element_s
{
67
cf_ll_element *
next
;
68
cf_ll_element *
prev
;
69
};
70
71
/**
72
* cf_ll
73
* the linked list container
74
*/
75
struct
cf_ll_s
{
76
cf_ll_element *
head
;
77
cf_ll_element *
tail
;
78
cf_ll_destructor
destroy_fn
;
79
uint32_t
sz
;
80
bool
uselock
;
81
#ifdef EXTERNAL_LOCKS
82
void
*
LOCK
;
83
#else
84
pthread_mutex_t
LOCK
;
85
#endif //EXTERNAL_LOCKS
86
};
87
88
/******************************************************************************
89
* INLINE FUNCTIONS
90
******************************************************************************/
91
92
static
inline
cf_ll_element *
cf_ll_get_head
(cf_ll *ll) {
93
return
(ll->head);
94
}
95
96
static
inline
cf_ll_element *
cf_ll_get_tail
(cf_ll *ll) {
97
return
(ll->tail);
98
}
99
100
static
inline
cf_ll_element *
cf_ll_get_next
(cf_ll_element *e) {
101
return
(e->next);
102
}
103
104
static
inline
cf_ll_element *
cf_ll_get_prev
(cf_ll_element *e) {
105
return
(e->prev);
106
}
107
108
/******************************************************************************
109
* FUNCTIONS
110
******************************************************************************/
111
112
/**
113
* Insert to head
114
*/
115
void
cf_ll_prepend
(cf_ll *ll, cf_ll_element *e );
116
117
/**
118
* Insert to tail
119
*/
120
void
cf_ll_append
(cf_ll *ll, cf_ll_element *e );
121
122
/**
123
* Insert after element !! warning! consider threadsafety before using this call!
124
*/
125
void
cf_ll_insert_after
(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
126
127
/**
128
* Insert before element !! warning! consider threadsafey before using this call!
129
*/
130
void
cf_ll_insert_before
(cf_ll *ll, cf_ll_element *cur, cf_ll_element *ins);
131
132
/**
133
* delete element - the real joy of a doubly linked list
134
* If a destructor function has been set, call it as well
135
*/
136
void
cf_ll_delete
(cf_ll *ll, cf_ll_element *e );
137
138
uint32_t
cf_ll_size
(cf_ll *ll);
139
140
/**
141
* The way these reduces work:
142
* ** If you're reducing and you want to delete this element, return CF_LL_REDUCE_DELETE
143
* and it'll be removed from the list - but iteration will not halt
144
* ** If you return a negative value, the reduction will terminate immediatly and that
145
* return value will be passed to the reducer
146
* ** The 'forward' parameter specifies whether you want to traverse from front to back,
147
* pass in 'false' to go tail-to-head
148
*/
149
int
cf_ll_reduce
( cf_ll *ll,
bool
forward,
cf_ll_reduce_fn
fn,
void
*udata);
150
151
/**
152
* Insert-before
153
* Sometimes you want to iterate a list, and insert before a certain element.
154
* Common when you're trying to keep a sorted list and you have some knowledge
155
* that either the list is short, or you're doing inserts of a particular pattern
156
* so that a sorted-table is not the right answer.
157
*
158
* Similar to the reduce function: if you want to bail out of the insert, return a negative
159
* If you want to insert "here", return the special code
160
* At the end of the list, you will be passed a null element (thus meaning you'll always
161
* be called at least once)
162
*/
163
int
cf_ll_insert_reduce
(cf_ll *ll, cf_ll_element *e,
bool
forward,
cf_ll_reduce_fn
fn,
void
*udata);
164
165
/**
166
* Call this function on a head structure to initialize it to empty
167
* Call with whether you want a locked version of a lockfree version
168
* if you're handling your own locks
169
*
170
* If you're using a standard delete methodology, then don't need a destructor function,
171
* and can leave it blank. But if you're using the reduce / delete pattern, then
172
* there's not an easy way for the application-level delete to occur, because you can't
173
* free the structure first then call delete. (you could insert the element on a queue,
174
* but it would have to carefully be a reference counted object, and then you'd still
175
* need the linked-list-reduceor to decrement the linked list....)
176
* In that case, you need to have a destructor
177
* function that gets fired every time a removal from the list occurs. even on explicit
178
* deletes it's called, just to be fancy.
179
*
180
* Note that when the destructor is called, the lock for the linked list is held
181
* (if you've allocated the linked list with a lock)
182
*/
183
int
cf_ll_init
(cf_ll *ll,
cf_ll_destructor
destroy_fn,
bool
uselock);
184
185
/******************************************************************************/
186
187
#ifdef __cplusplus
188
}
// end extern "C"
189
#endif