X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=queue.h;h=2a7193064e8412299a843cc604bd0a9a19888bf3;hb=a440874114b387c51fa2598f6b4117b0c17a3fbe;hp=cfa72b8d9f06e9bb8188abaa30e6e49aae26d995;hpb=33d2a71a7ea9304db47ba3b959c862b72f5c4bba;p=dragonstd.git diff --git a/queue.h b/queue.h index cfa72b8..2a71930 100644 --- a/queue.h +++ b/queue.h @@ -1,26 +1,89 @@ -#ifndef _DRAGONSTD_QUEUE_H_ +/* + Queue + ----- + + Thread safe FIFO data structure, using a List. + Useful for working with producer/consumer threads. +*/ + +#ifndef _DRAGONSTD_QUEUE_H_ // include guard #define _DRAGONSTD_QUEUE_H_ -#include -#include -#include -#include "list.h" - -typedef struct -{ - atomic_bool cancel; - bool finish; - List list; - pthread_cond_t cv; - pthread_mutex_t mtx; +#include // for pthread_cond_t, pthread_mutex_t +#include // for bool +#include "bits/callback.h" // for Transformer +#include "list.h" // for List + +typedef struct { + /* private */ + List lst; // list containing data + unsigned int cnl: 1; // cancel state + unsigned int fin: 1; // finish state + pthread_cond_t cnd; // condition variable for notifying consumer + pthread_mutex_t mtx; // mutex to protect the condition variable } Queue; -Queue *queue_create(); -void queue_delete(Queue *queue); -void queue_enqueue(Queue *queue, void *elem); -void *queue_dequeue(Queue *queue); -void *queue_dequeue_callback(Queue *queue, void (*callback)(void *elem)); -void queue_cancel(Queue *queue); // disallow dequeing -void queue_finish(Queue *queue); // disallow enqueing, wait until consumption finished +void queue_ini(Queue *queue); +/* + Initializes the queue. + + The queue should be uninitialized or deleted when passed to this function. +*/ + +void queue_del(Queue *queue); +/* + Delete the queue. + + Afterwards, the queue should no longer be used. + + This does not clear the underling list. Use queue_fin or queue_clr to make sure the + list is cleared before calling this function. +*/ + +void queue_clr(Queue *queue, Iterator func, void *arg); +/* + Clears the queue. + + Calls list_clr on the underling list. This is not thread safe. Use queue_fin instead + to wait for consumer threads to finish processing the data. +*/ + +bool queue_enq(Queue *queue, void *dat); +/* + [Thread Safe] + Enqueues an element to the back of the queue. + Returns true if the enqueueing was successful (this is always the case if queue_fin + has not been called) + + Notifies waiting consumer threads. +*/ + +void *queue_deq(Queue *queue, Transformer func); +/* + [Thread Safe] + Dequeue an element. + + If no element is in the queue, wait until there is one. + The (optional) transformer is called once an element is available and has been + dequeued and while the queue mutex is still locked. + + Note the the wait continues if the transformer returns NULL. +*/ + +void queue_cnl(Queue *queue); +/* + [Thread Safe] + Cancels dequeueing. + Subsequent calls to queue_deq immediately return NULL. +*/ + +void queue_fin(Queue *queue); // disallow enqueing, wait until consumption finished +/* + [Thread Safe] + Cancels enqueueing and waits for the queue to finish. + Subsequent calls to queue_enq have no effect and return false. + + Before returning, this function waits for the queue to be empty. +*/ -#endif +#endif // _DRAGONSTD_QUEUE_H_