VLC 4.0.0-dev
Loading...
Searching...
No Matches
vlc_queue.h
Go to the documentation of this file.
1/*****************************************************************************
2 * vlc_queue.h: generic queue functions
3 *****************************************************************************
4 * Copyright (C) 2020 RĂ©mi Denis-Courmont
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
20
21#ifndef VLC_QUEUE_H
22#define VLC_QUEUE_H
23
24/**
25 * @defgroup queue Thread-safe queues (FIFO)
26 * @ingroup cext
27 * @{
28 * @file vlc_queue.h
29 */
30
31#include <stdbool.h>
32#include <stdint.h>
33#include <vlc_common.h>
34#include <vlc_threads.h>
35
36/**
37 * Opaque type for queue entry.
38 */
39struct vlc_queue_entry;
40
41/**
42 * Thread-safe queue (a.k.a. FIFO).
43 */
44typedef struct vlc_queue
46 struct vlc_queue_entry *first;
47 struct vlc_queue_entry **lastp;
48 ptrdiff_t next_offset;
53/**
54 * Initializes a queue.
55 *
56 * @param queue storage space for the queue
57 * @param next_offset offset of the pointer to the next element
58 * within a queue entry (as per @c offsetof())
59 */
60VLC_API void vlc_queue_Init(vlc_queue_t *queue, ptrdiff_t next_offset);
61
62/**
63 * @defgroup queue_ll Queue internals
64 *
65 * Low-level queue functions.
66 *
67 * In some cases, the high-level queue functions do not exactly fit the
68 * use case requirements, and it is necessary to access the queue internals.
69 * This typically occurs when threads wait for elements to be added to the
70 * queue at the same time as some other type of events.
71 * @{
72 */
73/**
74 * Locks a queue.
75 *
76 * No more than one thread can lock a queue at any given time, and no other
77 * thread can modify the queue while it is locked.
78 * Accordingly, if the queue is already locked by another thread, this function
79 * waits.
80 *
81 * Use vlc_queue_Unlock() to release the lock.
82 *
83 * @warning Recursively locking a single queue is undefined.
84 * Also locking more than one queue at a time may lead to lock inversion:
85 * mind the locking order!
86 */
87static inline void vlc_queue_Lock(vlc_queue_t *q)
90}
91
92/**
93 * Unlocks a queue.
94 *
95 * This releases the lock on a queue, allowing other threads to manipulate the
96 * queue. The behaviour is undefined if the calling thread is not holding the
97 * queue lock.
98 */
99static inline void vlc_queue_Unlock(vlc_queue_t *q)
102}
103
104/**
105 * Wakes one thread waiting for a queue entry up.
106 */
107static inline void vlc_queue_Signal(vlc_queue_t *q)
110}
111
112/**
113 * Waits for a queue entry.
114 *
115 * @note This function is a cancellation point.
116 * In case of cancellation, the queue will be locked,
117 * as is consistent for condition variable semantics.
118 *
119 * @bug This function should probably not be aware of cancellation.
120 */
121static inline void vlc_queue_Wait(vlc_queue_t *q)
123 vlc_cond_wait(&q->wait, &q->lock);
124}
125
126/**
127 * Queues an entry (without locking).
128 *
129 * This function enqueues an entry, or rather a linked-list of entries, in a
130 * thread-safe queue, without taking the queue lock.
131 *
132 * @warning It is assumed that the caller already holds the queue lock;
133 * otherwise the behaviour is undefined.
134 *
135 * @param q A queue locked with ::vlc_queue_Lock
136 * @param entry NULL-terminated list of entries to queue
137 * (if NULL, this function has no effects)
138 */
140
141/**
142 * Dequeues the oldest entry (without locking).
143 *
144 * This function dequeues an entry from a thread-safe queue. It is assumed
145 * that the caller already holds the queue lock; otherwise the behaviour is
146 * undefined.
147 *
148 * @warning It is assumed that the caller already holds the queue lock;
149 * otherwise the behaviour is undefined.
150 *
151 * @return the first entry in the queue, or NULL if the queue is empty
152 */
154
155/**
156 * Dequeues all entries (without locking).
157 *
158 * This is equivalent to calling vlc_queue_DequeueUnlocked() repeatedly until
159 * the queue is emptied. However this function is much faster than that, as it
160 * does not need to update the linked-list pointers.
161 *
162 * @warning It is assumed that the caller already holds the queue lock;
163 * otherwise the behaviour is undefined.
164 *
165 * @return a linked-list of all entries (possibly NULL if none)
166 */
168
169/**
170 * Checks if a queue is empty (without locking).
171 *
172 * @warning It is assumed that the caller already holds the queue lock;
173 * otherwise the behaviour is undefined.
174 *
175 * @retval false the queue contains one or more entries
176 * @retval true the queue is empty
177 */
178VLC_USED static inline bool vlc_queue_IsEmpty(const vlc_queue_t *q)
180 return q->first == NULL;
181}
182
183/** @} */
184
185/**
186 * Queues an entry.
187 *
188 * This function enqueues an entry, or rather a linked-list of entries, in a
189 * thread-safe queue.
190 *
191 * @param q A queue initialized with ::vlc_queue_Init
192 * @param entry list of entries (if NULL, this function has no effects)
193 */
195
196/**
197 * Dequeues the oldest entry.
198 *
199 * This function dequeues an entry from a thread-safe queue. If the queue is
200 * empty, it will wait until at least one entry is available.
201 *
202 * @param queue queue object to dequeue an entry from
203 *
204 * @return the first entry in the queue, or NULL if the queue is empty
205 */
207
208/**
209 * Dequeues all entries.
210 *
211 * This is equivalent to calling vlc_queue_Dequeue() repeatedly until the queue
212 * is emptied. However this function is much faster than that, as it
213 * does not need to update the linked-list pointers.
214 *
215 * @return a linked-list of all entries (possibly NULL if none)
216 */
218
219/**
220 * @defgroup queue_killable Killable queues
221 *
222 * Thread-safe queues with an end flag.
223 *
224 * @{
225 */
226
227/**
228 * Marks a queue ended.
229 */
230static inline void vlc_queue_Kill(vlc_queue_t *q,
231 bool *restrict tombstone)
232{
234 *tombstone = true;
237}
238
239/**
240 * Dequeues one entry from a killable queue.
241 *
242 * @return an entry, or NULL if the queue is empty and has been ended.
243 */
244static inline void *vlc_queue_DequeueKillable(vlc_queue_t *q,
245 const bool *tombstone)
246{
247 void *entry;
248
250 while (vlc_queue_IsEmpty(q) && !*tombstone)
252
255 return entry;
256}
257
258/** @} */
259
260/** @} */
261#endif
#define VLC_USED
Definition fourcc_gen.c:32
#define VLC_API
Definition fourcc_gen.c:31
void vlc_cond_signal(vlc_cond_t *cond)
Wakes up one thread waiting on a condition variable.
Definition threads.c:193
void vlc_cond_wait(vlc_cond_t *cond, vlc_mutex_t *mutex)
Waits on a condition variable.
Definition threads.c:280
void vlc_mutex_unlock(vlc_mutex_t *mtx)
Releases a mutex.
Definition threads.c:149
void vlc_mutex_lock(vlc_mutex_t *mtx)
Acquires a mutex.
Definition threads.c:95
static void * vlc_queue_DequeueKillable(vlc_queue_t *q, const bool *tombstone)
Dequeues one entry from a killable queue.
Definition vlc_queue.h:245
static void vlc_queue_Kill(vlc_queue_t *q, bool *restrict tombstone)
Marks a queue ended.
Definition vlc_queue.h:231
static void vlc_queue_Lock(vlc_queue_t *q)
Locks a queue.
Definition vlc_queue.h:88
static void vlc_queue_Wait(vlc_queue_t *q)
Waits for a queue entry.
Definition vlc_queue.h:122
void vlc_queue_EnqueueUnlocked(vlc_queue_t *q, void *entry)
Queues an entry (without locking).
Definition queue.c:80
void * vlc_queue_DequeueAllUnlocked(vlc_queue_t *)
Dequeues all entries (without locking).
Definition queue.c:116
static void vlc_queue_Signal(vlc_queue_t *q)
Wakes one thread waiting for a queue entry up.
Definition vlc_queue.h:108
void * vlc_queue_DequeueUnlocked(vlc_queue_t *)
Dequeues the oldest entry (without locking).
Definition queue.c:96
static void vlc_queue_Unlock(vlc_queue_t *q)
Unlocks a queue.
Definition vlc_queue.h:100
static bool vlc_queue_IsEmpty(const vlc_queue_t *q)
Checks if a queue is empty (without locking).
Definition vlc_queue.h:179
void * vlc_queue_Dequeue(vlc_queue_t *queue)
Dequeues the oldest entry.
Definition queue.c:135
void * vlc_queue_DequeueAll(vlc_queue_t *)
Dequeues all entries.
Definition queue.c:151
struct vlc_queue vlc_queue_t
Thread-safe queue (a.k.a.
void vlc_queue_Enqueue(vlc_queue_t *q, void *entry)
Queues an entry.
Definition queue.c:128
void vlc_queue_Init(vlc_queue_t *queue, ptrdiff_t next_offset)
Initializes a queue.
Definition queue.c:71
Definition fourcc_gen.c:52
Condition variable.
Definition vlc_threads.h:270
Mutex.
Definition vlc_threads.h:143
Thread-safe queue (a.k.a.
Definition vlc_queue.h:46
struct vlc_queue_entry * first
Definition vlc_queue.h:47
struct vlc_queue_entry ** lastp
Definition vlc_queue.h:48
vlc_cond_t wait
Definition vlc_queue.h:51
vlc_mutex_t lock
Definition vlc_queue.h:50
ptrdiff_t next_offset
Definition vlc_queue.h:49
This file is a collection of common definitions and types.
Thread primitive declarations.