rlib
Convenience library for useful things
Loading...
Searching...
No Matches
rqueue.h
Go to the documentation of this file.
1/* RLIB - Convenience library for useful things
2 * Copyright (C) 2016 Haakon Sporsheim <haakon.sporsheim@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3.0 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library.
16 * See the COPYING file at the root of the source repository.
17 */
18#ifndef __R_QUEUE_H__
19#define __R_QUEUE_H__
20
21#if !defined(__RLIB_H_INCLUDE_GUARD__) && !defined(RLIB_COMPILATION)
22#error "#include <rlib.h> only please."
23#endif
24
49#include <rlib/rtypes.h>
50#include <rlib/rref.h>
51
52#include <rlib/data/rlist.h>
53
55
56/* RQueue is really just RQueueList */
58#define RQueue RQueueList
60#define R_QUEUE_INIT R_QUEUE_LIST_INIT
62#define r_queue_new r_queue_list_new
64#define r_queue_free r_queue_list_free
66#define r_queue_init r_queue_list_init
68#define r_queue_clear r_queue_list_clear
70#define r_queue_push r_queue_list_push
72#define r_queue_pop r_queue_list_pop
74#define r_queue_peek r_queue_list_peek
76#define r_queue_remove_link r_queue_list_remove_link
78#define r_queue_size r_queue_list_size
80#define r_queue_is_empty r_queue_list_is_empty
81
82
93typedef struct {
94 RList * head;
95 RList * tail;
98
100#define R_QUEUE_LIST_INIT { NULL, NULL, 0 }
102static inline RQueueList * r_queue_list_new (void) R_ATTR_MALLOC;
104static inline void r_queue_list_init (RQueueList * q);
106static inline void r_queue_list_free (RQueueList * q, RDestroyNotify notify);
108static inline void r_queue_list_clear (RQueueList * q, RDestroyNotify notify);
110static inline RList * r_queue_list_push (RQueueList * q, rpointer item);
112static inline rpointer r_queue_list_pop (RQueueList * q);
114static inline rpointer r_queue_list_peek (const RQueueList * q);
116static inline void r_queue_list_remove_link (RQueueList * q, RList * link);
118#define r_queue_list_size(q) (q)->size
120#define r_queue_list_is_empty(q) ((q)->size == 0)
121
132typedef struct {
133 RCBList * head;
134 RCBList * tail;
136} RCBQueue;
137
139static inline RCBQueue * r_cbqueue_new (void) R_ATTR_MALLOC;
141static inline void r_cbqueue_init (RCBQueue * q);
143static inline void r_cbqueue_free (RCBQueue * q);
145static inline void r_cbqueue_clear (RCBQueue * q);
147static inline RCBList * r_cbqueue_push (RCBQueue * q, RFunc cb,
148 rpointer data, RDestroyNotify datanotify, rpointer user, RDestroyNotify usernotify);
150static inline RCBList * r_cbqueue_pop (RCBQueue * q);
152static inline RCBList * r_cbqueue_peek (const RCBQueue * q);
154static inline void r_cbqueue_remove_link (RCBQueue * q, RCBList * link);
156static inline rsize r_cbqueue_call (RCBQueue * q);
163static inline rsize r_cbqueue_call_pop (RCBQueue * q);
165static inline void r_cbqueue_merge (RCBQueue * dst, RCBQueue * src);
167#define r_cbqueue_size(q) (q)->size
169#define r_cbqueue_is_empty(q) ((q)->size == 0)
170
171
184typedef struct RQueueRing RQueueRing;
186R_API RQueueRing * r_queue_ring_new (rsize size) R_ATTR_MALLOC;
188#define r_queue_ring_ref r_ref_ref
190#define r_queue_ring_unref r_ref_unref
191
208
214/******************************************************************************/
215/* Queue / Deque / Queue implemented with a list */
216/******************************************************************************/
217static inline RQueueList * r_queue_list_new (void)
218{
219 return r_mem_new0 (RQueueList);
220}
221static inline void r_queue_list_init (RQueueList * q)
222{
223 r_memset (q, 0, sizeof (RQueueList));
224}
225static inline void r_queue_list_free (RQueueList * q, RDestroyNotify notify)
226{
227 if (q != NULL) {
228 r_queue_list_clear (q, notify);
229 r_free (q);
230 }
231}
232static inline void r_queue_list_clear (RQueueList * q, RDestroyNotify notify)
233{
234 RList * head = q->head;
235 r_memset (q, 0, sizeof (RQueueList));
236 r_list_destroy_full (head, notify);
237}
238static inline RList * r_queue_list_push (RQueueList * q, rpointer item)
239{
240 RList * ret = r_list_alloc_copy (item);
241 if (q->size++ > 0) {
242 ret->prev = q->tail;
243 q->tail->next = ret;
244 q->tail = ret;
245 } else {
246 q->head = q->tail = ret;
247 }
248
249 return ret;
250}
252{
253 rpointer ret;
254 RList * it;
255
256 if ((it = q->head) != NULL) {
257 if ((q->head = it->next) != NULL)
258 q->head->prev = NULL;
259 else
260 q->tail = NULL;
261 ret = it->data;
262 r_list_free1 (it);
263
264 q->size--;
265 } else {
266 ret = NULL;
267 }
268
269 return ret;
270}
271static inline rpointer r_queue_list_peek (const RQueueList * q)
272{
273 return q->head != NULL ? q->head->data : NULL;
274}
275static inline void r_queue_list_remove_link (RQueueList * q, RList * link)
276{
277 if (link == q->tail)
278 q->tail = q->tail->prev;
279 q->head = r_list_destroy_link (q->head, link);
280 q->size--;
281}
282
283static inline RCBQueue * r_cbqueue_new (void)
284{
285 return r_mem_new0 (RCBQueue);
286}
287static inline void r_cbqueue_init (RCBQueue * q)
288{
289 r_memset (q, 0, sizeof (RCBQueue));
290}
291static inline void r_cbqueue_free (RCBQueue * q)
292{
293 if (q != NULL) {
294 r_cbqueue_clear (q);
295 r_free (q);
296 }
297}
298static inline void r_cbqueue_clear (RCBQueue * q)
299{
300 RCBList * head = q->head;
301 r_memset (q, 0, sizeof (RCBQueue));
302 r_cblist_destroy (head);
303}
304static inline RCBList * r_cbqueue_push (RCBQueue * q, RFunc cb,
305 rpointer data, RDestroyNotify datanotify, rpointer user, RDestroyNotify usernotify)
306{
307 RCBList * n = r_cblist_alloc_full (cb, data, datanotify, user, usernotify);
308 if (q->size++ > 0) {
309 n->prev = q->tail;
310 q->tail->next = n;
311 q->tail = n;
312 } else {
313 q->tail = q->head = n;
314 }
315
316 return n;
317}
318static inline RCBList * r_cbqueue_pop (RCBQueue * q)
319{
320 RCBList * ret;
321
322 if ((ret = q->head) != NULL) {
323 if ((q->head = ret->next) != NULL)
324 q->head->prev = NULL;
325 else
326 q->tail = NULL;
327 ret->prev = NULL;
328
329 q->size--;
330 } else {
331 ret = NULL;
332 }
333
334 return ret;
335}
336static inline RCBList * r_cbqueue_peek (const RCBQueue * q)
337{
338 return q->head;
339}
340static inline void r_cbqueue_remove_link (RCBQueue * q, RCBList * link)
341{
342 if (link == q->tail)
343 q->tail = q->tail->prev;
344 q->head = r_cblist_destroy_link (q->head, link);
345 q->size--;
346}
347static inline rsize r_cbqueue_call (RCBQueue * q)
348{
349 return r_cblist_call (q->head);
350}
351
353{
354 rsize ret;
355 RCBList * lst = q->head;
356 r_memset (q, 0, sizeof (RCBQueue));
357 ret = r_cblist_call (lst);
358 r_cblist_destroy (lst);
359 return ret;
360}
361static inline void r_cbqueue_merge (RCBQueue * dst, RCBQueue * src)
362{
363 if (dst->size > 0 && src->size > 0) {
364 dst->size += src->size;
365
366 dst->tail->next = src->head;
367 src->head->prev = dst->tail;
368 dst->tail = src->tail;
369 } else if (dst->size == 0) {
370 r_memcpy (dst, src, sizeof (RCBQueue));
371 }
372
373 r_memset (src, 0, sizeof (RCBQueue));
374}
375
376R_END_DECLS
377
380#endif /* __R_QUEUE_H__ */
381
RCBList * r_cblist_alloc_full(RFunc cb, rpointer data, RDestroyNotify datanotify, rpointer user, RDestroyNotify usernotify)
Allocate a standalone callback node with full ownership wiring.
rsize r_cblist_call(RCBList *head)
Invoke every callback in the list in order; returns the number called.
#define NULL
Null pointer constant (defined only if absent).
Definition rmacros.h:126
#define R_ATTR_WARN_UNUSED_RESULT
Warn if a function's return value is ignored.
Definition rmacros.h:278
#define R_API
Public-API decoration: resolves to R_API_EXPORT while building rlib and R_API_IMPORT for consumers.
Definition rmacros.h:115
#define R_BEGIN_DECLS
Open an extern "C" block under C++ (no-op in C).
Definition rmacros.h:196
static rpointer r_memset(rpointer a, int v, rsize size)
Fill size bytes at a with byte value v.
Definition rmemops.h:97
static rpointer r_memcpy(void *R_ATTR_RESTRICT dst, const void *R_ATTR_RESTRICT src, rsize size)
Copy size bytes from src to dst.
Definition rmemops.h:121
#define r_mem_new0(type)
Allocate a single zeroed instance of type.
Definition rmem.h:193
void r_free(rpointer ptr)
Release a heap allocation obtained from r_malloc / r_malloc0 / r_calloc / r_realloc.
static void r_cbqueue_clear(RCBQueue *q)
Drop all callbacks, running destroy notifiers.
Definition rqueue.h:298
static RList * r_queue_list_push(RQueueList *q, rpointer item)
Append item to the tail; returns the new list node.
Definition rqueue.h:238
rpointer r_queue_ring_peek(RQueueRing *q)
Peek at the head item without removing it.
static RCBList * r_cbqueue_pop(RCBQueue *q)
Detach and return the head node; caller is responsible for invoking / freeing.
Definition rqueue.h:318
static rsize r_cbqueue_call_pop(RCBQueue *q)
Atomically detach + invoke + drop the queue's callbacks.
Definition rqueue.h:352
static void r_cbqueue_merge(RCBQueue *dst, RCBQueue *src)
Concatenate src onto dst; src ends up empty.
Definition rqueue.h:361
struct RQueueRing RQueueRing
Opaque, refcounted ring-buffer queue.
Definition rqueue.h:184
static RCBList * r_cbqueue_peek(const RCBQueue *q)
Peek at the head node.
Definition rqueue.h:336
static rsize r_cbqueue_call(RCBQueue *q)
Invoke every callback currently queued; returns the number called.
Definition rqueue.h:347
static RCBList * r_cbqueue_push(RCBQueue *q, RFunc cb, rpointer data, RDestroyNotify datanotify, rpointer user, RDestroyNotify usernotify)
Append a callback to the tail; returns the new node.
Definition rqueue.h:304
static void r_queue_list_free(RQueueList *q, RDestroyNotify notify)
Free a heap-allocated queue, calling notify on each item.
Definition rqueue.h:225
static RCBQueue * r_cbqueue_new(void)
Heap-allocate an empty RCBQueue.
Definition rqueue.h:283
static rpointer r_queue_list_peek(const RQueueList *q)
Peek at the head item without removing it.
Definition rqueue.h:271
static RQueueList * r_queue_list_new(void)
Heap-allocate an empty RQueueList.
Definition rqueue.h:217
RQueueRing * r_queue_ring_new(rsize size)
Construct a ring queue with capacity size (rounded up to a power of 2).
rboolean r_queue_ring_is_empty(RQueueRing *q)
TRUE iff q has no items.
static void r_cbqueue_free(RCBQueue *q)
Free a heap-allocated callback queue; runs each callback's destroy notifiers.
Definition rqueue.h:291
static rpointer r_queue_list_pop(RQueueList *q)
Remove and return the head item, or NULL when empty.
Definition rqueue.h:251
static void r_cbqueue_init(RCBQueue *q)
Initialise a stack-allocated RCBQueue.
Definition rqueue.h:287
static void r_queue_list_init(RQueueList *q)
Initialise a stack-allocated RQueueList.
Definition rqueue.h:221
rsize r_queue_ring_size(RQueueRing *q)
Number of items currently in q.
static void r_queue_list_clear(RQueueList *q, RDestroyNotify notify)
Drop every item from q, calling notify on each.
Definition rqueue.h:232
rboolean r_queue_ring_push(RQueueRing *q, rpointer item) R_ATTR_WARN_UNUSED_RESULT
Push item onto the tail.
rpointer r_queue_ring_pop(RQueueRing *q)
Remove and return the head item, or NULL when empty.
void r_queue_ring_clear(RQueueRing *q, RDestroyNotify notify)
Drop every item, calling notify on each.
static void r_queue_list_remove_link(RQueueList *q, RList *link)
Remove an arbitrary link from q.
Definition rqueue.h:275
static void r_cbqueue_remove_link(RCBQueue *q, RCBList *link)
Remove an arbitrary link from q.
Definition rqueue.h:340
int rboolean
Boolean type (typedef'd to int).
Definition rtypes.h:59
void(* RFunc)(rpointer data, rpointer user)
Generic iteration callback over (data, user) pairs.
Definition rtypes.h:403
void(* RDestroyNotify)(rpointer ptr)
Destructor callback: free / release the value at ptr.
Definition rtypes.h:401
void * rpointer
Generic pointer (alias for void *).
Definition rtypes.h:327
unsigned long rsize
Unsigned pointer-sized size type (like size_t).
Definition rtypes.h:290
Linked-list types: doubly / singly linked plus the callback-flavoured specialisations.
Refcount base struct shared by every refcounted type in rlib.
Foundational type aliases used by every rlib header.
List-backed queue of RFuncCallbackCtx entries.
Definition rqueue.h:132
RCBList * head
Definition rqueue.h:133
RCBList * tail
Definition rqueue.h:134
rsize size
Definition rqueue.h:135
List-backed FIFO / deque.
Definition rqueue.h:93
rsize size
Definition rqueue.h:96
RList * tail
Definition rqueue.h:95
RList * head
Definition rqueue.h:94