PaStiX Handbook 6.4.0
Loading...
Searching...
No Matches
queue.c
Go to the documentation of this file.
1/**
2 *
3 * @file queue.c
4 *
5 * PaStiX queue structure.
6 *
7 * @copyright 2004-2025 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8 * Univ. Bordeaux. All rights reserved.
9 *
10 * @version 6.4.0
11 * @author Pascal Henon
12 * @author Mathieu Faverge
13 * @author Pierre Ramet
14 * @author Tony Delarue
15 * @date 2024-07-05
16 *
17 * @addtogroup blend_dev_queue
18 * @{
19 *
20 **/
21#include <stdio.h>
22#include "common.h"
23#include "queue.h"
24
25/**
26 *******************************************************************************
27 *
28 * @brief Compare two items of the queue based on the couple (key1, key2).
29 *
30 *******************************************************************************
31 *
32 * @param[in] item1
33 * The first item to compare.
34 *
35 * @param[in] item2
36 * The second item to compare.
37 *
38 *******************************************************************************
39 *
40 * @retval 1 if item1 < item2
41 * @retval 0 otherwise
42 *
43 *******************************************************************************/
44static inline int
46 const pastix_queue_item_t *item2)
47{
48 /* if elt1 < elt2 return 1 */
49 /* if elt1 = elt2 return 0 */
50 /* if elt1 > elt2 return 0 */
51
52 if ( item1->key1 == item2->key1) {
53 return item1->key2 < item2->key2;
54 }
55 else {
56 return item1->key1 < item2->key1;
57 }
58}
59
60/**
61 *******************************************************************************
62 *
63 * @brief Initialize the queue structure with an initial space to store the
64 * elements.
65 *
66 *******************************************************************************
67 *
68 * @param[inout] q
69 * The qallocated pointer to the queue to initialize.
70 *
71 * @param[in] size
72 * The initial size for the queue.
73 *
74 *******************************************************************************
75 *
76 * @retval PASTIX_SUCCESS if success.
77 * @retval PASTIX_ERR_OUTOFMEMORY if malloc failed.
78 *
79 *******************************************************************************/
80int
82 pastix_int_t size)
83{
84 q->size = size;
85 q->used = 0;
86 q->lock = PASTIX_ATOMIC_UNLOCKED;
87 if (q->size != 0)
88 {
89 MALLOC_INTERN(q->elttab, size, pastix_queue_item_t);
90 }
91 else
92 {
93 q->elttab = NULL;
94 }
95 return PASTIX_SUCCESS;
96}
97
98/**
99 *******************************************************************************
100 *
101 * @brief Free the structure associated to the queue.
102 *
103 *******************************************************************************
104 *
105 * @param[inout] q
106 * The pointer to the queue to free.
107 *
108 *******************************************************************************/
109void
111{
112 if(q->size != 0)
113 {
114 memFree_null(q->elttab);
115 }
116 q->size = 0;
117}
118
119/**
120 *******************************************************************************
121 *
122 * @brief Return the size of the queue.
123 *
124 *******************************************************************************
125 *
126 * @param[in] q
127 * The pointer to the queue.
128 *
129 *******************************************************************************
130 *
131 * @return The size of the queue.
132 *
133 *******************************************************************************/
136{
137 return q->used;
138}
139
140/**
141 *******************************************************************************
142 *
143 * @brief Reset the number of used element to 0.
144 *
145 *******************************************************************************
146 *
147 * @param[inout] q
148 * The pointer to the queue.
149 *
150 *******************************************************************************/
151void
153{
154 q->used = 0;
155}
156
157/**
158 *******************************************************************************
159 *
160 * @brief Insert an element into the sorted queue.
161 *
162 *******************************************************************************
163 *
164 * @param[inout] q
165 * The pointer to the queue.
166 *
167 * @param[in] elt
168 * The element to insert in the queue.
169 *
170 * @param[in] key1
171 * The first key of the element.
172 *
173 * @param[in] key2
174 * The second key of the element.
175 *
176 *******************************************************************************/
177void
179 pastix_int_t elt,
180 double key1,
181 double key2)
182{
183 pastix_atomic_lock( &(q->lock) );
184 pastix_int_t i, hi;
185
186 /* Allocate more space if necessary */
187 if(q->size == q->used)
188 {
190 tmp = q->elttab;
191
192 assert( (q->size == 0) || (tmp != NULL) );
193
194 MALLOC_INTERN(q->elttab, q->size*2+1, pastix_queue_item_t);
195 memcpy(q->elttab, tmp, q->size * sizeof(pastix_queue_item_t));
196
197 q->size = q->size*2 +1;
198 memFree_null(tmp);
199 }
200
201 q->elttab[q->used].key1 = key1;
202 q->elttab[q->used].key2 = key2;
203 q->elttab[q->used].eltptr = elt;
204 q->used++;
205
206 i = q->used - 1;
207 hi= (i+1)/2-1;
208
209 while( (i > 0) &&
211 q->elttab + hi) )
212 {
213 pastix_queue_item_t swap = q->elttab[i];
214
215 q->elttab[i ] = q->elttab[hi];
216 q->elttab[hi] = swap;
217
218 i = hi; hi = (i+1)/2-1;
219 }
220 pastix_atomic_unlock( &(q->lock) );
221}
222
223/**
224 *******************************************************************************
225 *
226 * @brief Read the first element of the queue.
227 *
228 *******************************************************************************
229 *
230 * @param[in] q
231 * The pointer to the queue.
232 *
233 *******************************************************************************
234 *
235 * @return The value of the first element sorted by (key1, key2).
236 *
237 *******************************************************************************/
240{
241 return q->elttab[0].eltptr;
242}
243
244/**
245 *******************************************************************************
246 *
247 * @brief Remove the first element of the queue and return its keys if needed.
248 *
249 *******************************************************************************
250 *
251 * @param[inout] q
252 * The pointer to the queue. On exit, the queue without its head.
253 *
254 * @param[out] key1
255 * If key1 != NULL, stores the associated key1 to the first element on
256 * exit.
257 *
258 * @param[out] key2
259 * If key2 != NULL, stores the associated key2 to the first element on
260 * exit.
261 *
262 *******************************************************************************
263 *
264 * @return The value of the first element sorted by (key1, key2).
265 *
266 *******************************************************************************/
268pqueuePop2(pastix_queue_t *q, double *key1, double*key2)
269{
270 pastix_atomic_lock( &(q->lock) );
271 pastix_int_t i, j;
272 pastix_int_t return_elt;
273
274 if (q->used == 0) {
275 pastix_atomic_unlock( &(q->lock) );
276 pastix_yield();
277 return -1;
278 }
279
280 return_elt = q->elttab[0].eltptr;
281 if (key1 != NULL) { *key1 = q->elttab[0].key1; }
282 if (key2 != NULL) { *key2 = q->elttab[0].key2; }
283
284 q->elttab[0] = q->elttab[q->used-1];
285 q->used--;
286
287 i = 1;
288 while(i <= (q->used/2))
289 {
290 if( (2*i == q->used)
291 || pqueueItemComparison(q->elttab + 2*i-1,
292 q->elttab + 2*i ) ) /*(q->keytab[2*i-1] < q->keytab[2*i]))*/
293 {
294 j = 2*i;
295 }
296 else
297 {
298 j = 2*i+1;
299 }
300 if (!pqueueItemComparison(q->elttab + i-1,
301 q->elttab + j-1)) /*(q->keytab[i-1] >= q->keytab[j-1])*/
302 {
304
305 swap = q->elttab[i-1];
306 q->elttab[i-1] = q->elttab[j-1];
307 q->elttab[j-1] = swap;
308
309 i = j;
310 }
311 else {
312 break;
313 }
314 }
315 pastix_atomic_unlock( &(q->lock) );
316 return return_elt;
317}
318
319/**
320 *******************************************************************************
321 *
322 * @brief Print the queue.
323 *
324 * Print the queue elements for debug. They are not printed in a sorted order,
325 * but in the order they are stored in the queue.
326 *
327 *******************************************************************************
328 *
329 * @param[in] q
330 * The pointer to the queue.
331 *
332 *******************************************************************************/
333void
335{
336 pastix_queue_item_t *item = q->elttab;
337 pastix_int_t i;
338
339 fprintf(stderr, "Queue :\n");
340 for (i = 0; i < q->used; i++, item++) {
341 fprintf(stderr, "(%ld %ld %ld) ",
342 (long)(item->eltptr),
343 (long)(item->key1),
344 (long)(item->key2) );
345 if (i%4 == 3) {
346 fprintf(stderr, "\n");
347 }
348 }
349 fprintf(stderr, "\n");
350}
351
352/**
353 *@}
354 */
BEGIN_C_DECLS typedef int pastix_int_t
Definition datatypes.h:51
pastix_int_t size
Definition queue.h:39
pastix_atomic_lock_t lock
Definition queue.h:42
pastix_int_t eltptr
Definition queue.h:32
pastix_queue_item_t * elttab
Definition queue.h:41
volatile pastix_int_t used
Definition queue.h:40
void pqueuePush2(pastix_queue_t *, pastix_int_t, double, double)
Insert an element into the sorted queue.
Definition queue.c:178
pastix_int_t pqueueRead(const pastix_queue_t *)
Read the first element of the queue.
Definition queue.c:239
void pqueueClear(pastix_queue_t *)
Reset the number of used element to 0.
Definition queue.c:152
void pqueueExit(pastix_queue_t *)
Free the structure associated to the queue.
Definition queue.c:110
pastix_int_t pqueuePop2(pastix_queue_t *, double *, double *)
Remove the first element of the queue and return its keys if needed.
Definition queue.c:268
void pqueuePrint(const pastix_queue_t *)
Print the queue.
Definition queue.c:334
pastix_int_t pqueueSize(const pastix_queue_t *)
Return the size of the queue.
Definition queue.c:135
int pqueueInit(pastix_queue_t *, pastix_int_t)
Initialize the queue structure with an initial space to store the elements.
Definition queue.c:81
static int pqueueItemComparison(const pastix_queue_item_t *item1, const pastix_queue_item_t *item2)
Compare two items of the queue based on the couple (key1, key2).
Definition queue.c:45
Queue item structure.
Definition queue.h:29
Queue structure.
Definition queue.h:38
@ PASTIX_SUCCESS
Definition api.h:367