All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
target/Linux-x86_64/include/citrusleaf/cf_queue.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 #include <pthread.h>
25 #include <citrusleaf/cf_types.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /******************************************************************************
32  * CONSTANTS
33  ******************************************************************************/
34 
35 #ifndef CF_QUEUE_ALLOCSZ
36 #define CF_QUEUE_ALLOCSZ 64
37 #endif
38 
39 #define CF_QUEUE_OK 0
40 #define CF_QUEUE_ERR -1
41 #define CF_QUEUE_EMPTY -2
42 #define CF_QUEUE_NOMATCH -3 // used in cf_queue_priority_reduce_pop
43 
44 // mswait < 0 wait forever
45 // mswait == 0 wait not at all
46 // mswait > 0 wait that number of ms
47 #define CF_QUEUE_FOREVER -1
48 #define CF_QUEUE_NOWAIT 0
49 
50 /******************************************************************************
51  * TYPES
52  ******************************************************************************/
53 
54 typedef int (*cf_queue_reduce_fn) (void *buf, void *udata);
55 
56 /**
57  * cf_queue
58  * A queue
59  */
60 struct cf_queue_s {
61  bool threadsafe; // sometimes it's good to live dangerously
62  unsigned int allocsz; // number of queue elements currently allocated
63  unsigned int write_offset; // 0 offset is first queue element.
64  // write is always greater than or equal to read
65  unsigned int read_offset; //
66  size_t elementsz; // number of bytes in an element
67  pthread_mutex_t LOCK; // the mutex lock
68  pthread_cond_t CV; // the condvar
69  byte * queue; // the actual bytes that make up the queue
70 };
71 
72 typedef struct cf_queue_s cf_queue;
73 
74 /******************************************************************************
75  * FUNCTIONS
76  ******************************************************************************/
77 
78 cf_queue * cf_queue_create(size_t elementsz, bool threadsafe);
79 
80 void cf_queue_destroy(cf_queue *q);
81 
82 /**
83  * Get the number of elements currently in the queue
84  */
85 int cf_queue_sz(cf_queue *q);
86 
87 /**
88  * Always pushes to the end of the queue
89  */
90 int cf_queue_push(cf_queue *q, void *ptr);
91 
92 /**
93  * Push element on the queue only if size < limit.
94  */
95 bool cf_queue_push_limit(cf_queue *q, void *ptr, uint limit);
96 
97 /**
98  * Same as cf_queue_push() except it's a no-op if element is already queued.
99  */
100 int cf_queue_push_unique(cf_queue *q, void *ptr);
101 
102 /**
103  * Push head goes to the front, which currently means memcpying the entire queue contents.
104  */
105 int cf_queue_push_head(cf_queue *q, void *ptr);
106 
107 /**
108  * POP pops from the end of the queue, which is the most efficient
109  * But understand this makes it LIFO, the least fair of queues
110  * Elements added at the very beginning might not make it out
111  */
112 int cf_queue_pop(cf_queue *q, void *buf, int mswait);
113 
114 /**
115  * Run the entire queue, calling the callback, with the lock held.
116  * You can return values in the callback to cause deletes.
117  * Great for purging dying stuff out of a queue synchronously.
118  *
119  * return -2 from the callback to trigger a delete
120  * return -1 stop iterating the queue
121  * return 0 for success
122  */
123 int cf_queue_reduce(cf_queue *q, cf_queue_reduce_fn cb, void *udata);
124 
125 /**
126  * Run the entire queue in reverse order, calling the callback, with the lock held.
127  * You can return values in the callback to cause deletes.
128  * Great for purging dying stuff out of a queue synchronously.
129  *
130  * return -2 from the callback to trigger a delete
131  * return -1 stop iterating the queue
132  * return 0 for success
133  */
134 int cf_queue_reduce_reverse(cf_queue *q, cf_queue_reduce_fn cb, void *udata);
135 
136 /**
137  * The most common reason to want to 'reduce' is delete - so provide
138  * a simple delete function
139  */
140 int cf_queue_delete(cf_queue *q, void *buf, bool only_one);
141 
142 /**
143  * Delete all items in queue.
144  */
145 int cf_queue_delete_all(cf_queue *q);
146 
147 void cf_queue_delete_offset(cf_queue *q, uint index);
148 
149 /******************************************************************************
150  * MACROS
151  ******************************************************************************/
152 
153 #define CF_Q_SZ(__q) (__q->write_offset - __q->read_offset)
154 
155 #define CF_Q_EMPTY(__q) (__q->write_offset == __q->read_offset)
156 
157 /**
158  * todo: maybe it's faster to keep the read and write offsets in bytes,
159  * to avoid the extra multiply?
160  */
161 #define CF_Q_ELEM_PTR(__q, __i) (&__q->queue[ (__i % __q->allocsz) * __q->elementsz ] )
162 
163 /******************************************************************************/
164 
165 #ifdef __cplusplus
166 } // end extern "C"
167 #endif