2 Copyright (C) 2001-2007, The Perl Foundation.
7 src/tsq.c - Thread-safe queues
19 #include "parrot/parrot.h"
21 /* HEADERIZER HFILE: include/parrot/tsq.h */
25 =item C<QUEUE_ENTRY * pop_entry>
27 Does a synchronized removal of the head entry off the queue and returns it.
33 PARROT_CAN_RETURN_NULL
35 pop_entry(ARGMOD(QUEUE
*queue
))
37 QUEUE_ENTRY
*returnval
;
39 returnval
= nosync_pop_entry(queue
);
46 =item C<QUEUE_ENTRY * peek_entry>
48 This does no locking, so the result might have changed by the time you
49 get the entry, but a synchronized C<pop_entry()> will check again and
50 return C<NULL> if the queue is empty.
56 PARROT_CAN_RETURN_NULL
57 PARROT_WARN_UNUSED_RESULT
59 peek_entry(ARGIN(const QUEUE
*queue
))
66 =item C<QUEUE_ENTRY * nosync_pop_entry>
68 Grab an entry off the queue with no synchronization. Internal only,
69 because it's darned evil and shouldn't be used outside the module. It's
70 in here so we don't have to duplicate pop code.
76 PARROT_CAN_RETURN_NULL
78 nosync_pop_entry(ARGMOD(QUEUE
*queue
))
80 QUEUE_ENTRY
*returnval
;
84 returnval
= queue
->head
;
85 if (queue
->head
== queue
->tail
) {
90 queue
->head
= queue
->head
->next
;
92 returnval
->next
= NULL
;
98 =item C<QUEUE_ENTRY * wait_for_entry>
100 Does a synchronized removal of the head entry off the queue, waiting if
101 necessary until there is an entry, and then returns it.
107 PARROT_CAN_RETURN_NULL
109 wait_for_entry(ARGMOD(QUEUE
*queue
))
111 QUEUE_ENTRY
*returnval
;
114 while (queue
->head
== NULL
) {
117 returnval
= nosync_pop_entry(queue
);
125 =item C<void push_entry>
127 Does a synchronized insertion of C<entry> onto the tail of the queue.
134 push_entry(ARGMOD(QUEUE
*queue
), ARGIN(QUEUE_ENTRY
*entry
))
137 /* Is there something in the queue? */
139 queue
->tail
->next
= entry
;
146 queue_signal(queue
); /* assumes only one waiter */
152 =item C<void unshift_entry>
154 Does a synchronized insertion of C<entry> into the head of the queue.
161 unshift_entry(ARGMOD(QUEUE
*queue
), ARGIN(QUEUE_ENTRY
*entry
))
168 /* empty just set head */
182 =item C<void nosync_insert_entry>
184 Inserts a timed event according to C<abstime>. The caller has to hold the
192 nosync_insert_entry(ARGMOD(QUEUE
*queue
), ARGIN(QUEUE_ENTRY
*entry
))
194 QUEUE_ENTRY
*cur
= queue
->head
;
199 PARROT_ASSERT(entry
->type
== QUEUE_ENTRY_TYPE_TIMED_EVENT
);
201 * empty queue - just insert
210 event
= (parrot_event
*)entry
->data
;
211 abs_time
= event
->u
.timer_event
.abs_time
;
213 while (cur
&& cur
->type
== QUEUE_ENTRY_TYPE_TIMED_EVENT
) {
214 const parrot_event
* const cur_event
= (parrot_event
*)cur
->data
;
215 if (abs_time
> cur_event
->u
.timer_event
.abs_time
) {
226 if (prev
== queue
->tail
)
234 =item C<void insert_entry>
236 Does a synchronized insert of C<entry>.
243 insert_entry(ARGMOD(QUEUE
*queue
), ARGIN(QUEUE_ENTRY
*entry
))
246 nosync_insert_entry(queue
, entry
);
253 =item C<void queue_lock>
255 Locks the queue's mutex.
262 queue_lock(ARGMOD(QUEUE
*queue
))
264 LOCK(queue
->queue_mutex
);
269 =item C<void queue_unlock>
271 Unlocks the queue's mutex.
278 queue_unlock(ARGMOD(QUEUE
*queue
))
280 UNLOCK(queue
->queue_mutex
);
285 =item C<void queue_broadcast>
287 This function wakes up I<every> thread waiting on the queue.
294 queue_broadcast(ARGMOD(QUEUE
*queue
))
296 COND_BROADCAST(queue
->queue_condition
);
301 =item C<void queue_signal>
303 XXX Needs a description
310 queue_signal(ARGMOD(QUEUE
*queue
))
312 COND_SIGNAL(queue
->queue_condition
);
317 =item C<void queue_wait>
319 Instructs the queue to wait.
326 queue_wait(ARGMOD(QUEUE
*queue
))
328 COND_WAIT(queue
->queue_condition
, queue
->queue_mutex
);
333 =item C<void queue_timedwait>
335 Instructs the queue to wait for C<abs_time> seconds (?).
342 queue_timedwait(ARGMOD(QUEUE
*queue
), ARGIN(const struct timespec
*abs_time
))
344 COND_TIMED_WAIT(queue
->queue_condition
, queue
->queue_mutex
, abs_time
);
349 =item C<QUEUE* queue_init>
351 Initializes the queue, setting C<prio> as the queue's priority.
357 PARROT_CAN_RETURN_NULL
360 queue_init(UINTVAL prio
)
362 QUEUE
* const queue
= mem_allocate_typed(QUEUE
);
364 queue
->head
= queue
->tail
= NULL
;
365 queue
->max_prio
= prio
;
366 COND_INIT(queue
->queue_condition
);
367 MUTEX_INIT(queue
->queue_mutex
);
373 =item C<void queue_destroy>
375 Destroys the queue, raising an exception if it is not empty.
382 queue_destroy(ARGMOD(QUEUE
*queue
))
384 if (peek_entry(queue
))
385 internal_exception(1, "Queue not empty on destroy");
387 COND_DESTROY(queue
->queue_condition
);
388 MUTEX_DESTROY(queue
->queue_mutex
);
398 F<include/parrot/tsq.h>.
407 * c-file-style: "parrot"
409 * vim: expandtab shiftwidth=4: