1 /*****************************************************************************
2 * queue.c: generic queue (FIFO)
3 *****************************************************************************
4 * Copyright (C) 2020 RĂ©mi Denis-Courmont
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.
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.
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 *****************************************************************************/
29 #include <vlc_common.h>
30 #include <vlc_queue.h>
32 /* Opaque struct type.
34 * ISO C uses the same representation for all pointer-to-struct types.
35 * Still different pointer types are not compatible, i.e. cannot alias.
36 * So use memcpy() to read/write pointer values.
38 struct vlc_queue_entry
;
40 static void entry_set(struct vlc_queue_entry
**pp
, struct vlc_queue_entry
*e
)
42 memcpy(pp
, &e
, sizeof (e
));
45 static struct vlc_queue_entry
*entry_get(struct vlc_queue_entry
*const *pp
)
47 struct vlc_queue_entry
*e
;
49 memcpy(&e
, pp
, sizeof (e
));
53 static struct vlc_queue_entry
**next_p(const struct vlc_queue_entry
*e
,
56 return (struct vlc_queue_entry
**)(((unsigned char *)e
) + offset
);
59 static void next_set(struct vlc_queue_entry
*e
, struct vlc_queue_entry
*next
,
62 entry_set(next_p(e
, offset
), next
);
65 static struct vlc_queue_entry
*next_get(const struct vlc_queue_entry
*e
,
68 return entry_get(next_p(e
, offset
));
71 void vlc_queue_Init(vlc_queue_t
*q
, ptrdiff_t next_offset
)
75 q
->next_offset
= next_offset
;
76 vlc_mutex_init(&q
->lock
);
77 vlc_cond_init(&q
->wait
);
80 void vlc_queue_EnqueueUnlocked(vlc_queue_t
*q
, void *entry
)
82 struct vlc_queue_entry
**lastp
;
83 const ptrdiff_t offset
= q
->next_offset
;
85 vlc_mutex_assert(&q
->lock
);
86 assert(entry_get(q
->lastp
) == NULL
);
87 entry_set(q
->lastp
, entry
);
89 for (lastp
= q
->lastp
; entry
!= NULL
; entry
= next_get(entry
, offset
))
90 lastp
= next_p(entry
, offset
);
96 void *vlc_queue_DequeueUnlocked(vlc_queue_t
*q
)
98 vlc_mutex_assert(&q
->lock
);
100 void *entry
= q
->first
;
101 const ptrdiff_t offset
= q
->next_offset
;
104 struct vlc_queue_entry
*next
= next_get(entry
, offset
);
106 next_set(entry
, NULL
, offset
);
110 q
->lastp
= &q
->first
;
116 void *vlc_queue_DequeueAllUnlocked(vlc_queue_t
*q
)
118 vlc_mutex_assert(&q
->lock
);
120 void *entry
= q
->first
;
123 q
->lastp
= &q
->first
;
128 void vlc_queue_Enqueue(vlc_queue_t
*q
, void *entry
)
131 vlc_queue_EnqueueUnlocked(q
, entry
);
135 void *vlc_queue_Dequeue(vlc_queue_t
*q
)
142 while (vlc_queue_IsEmpty(q
))
145 entry
= vlc_queue_DequeueUnlocked(q
);
151 void *vlc_queue_DequeueAll(vlc_queue_t
*q
)
156 entry
= vlc_queue_DequeueAllUnlocked(q
);