1 /* Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file chunk_queue.c Queuing functions for paraslash senders. */
12 #include "chunk_queue.h"
15 * Senders may use the chunk queue facility to deal with laggy connections. It
16 * allows them to enqueue chunks if they can not be sent out immediately.
18 * Chunk queues are "cheap" in the sense that only reference to the audio file
19 * data is stored, but not the data itself.
22 /** The list of pending chunks for this client. */
24 /** The number of pending bytes for this client. */
25 unsigned long num_pending;
26 /** More than that many bytes in the queue is considered an error. */
27 unsigned long max_pending;
30 /** Describes one queued chunk in a chunk queue. */
32 /** Pointer to the data to be queued. */
34 /** The number of bytes of this chunk. */
36 /** Position of the chunk in the chunk queue. */
37 struct list_head node;
41 * Add a chunk to the given queue.
43 * \param cq the queue to add the chunk to.
44 * \param buf Pointer to the data to be queued.
45 * \param num_bytes The size of \a buf.
49 int cq_enqueue(struct chunk_queue *cq, const char *buf, size_t num_bytes)
51 struct queued_chunk *qc;
53 if (cq->num_pending + num_bytes > cq->max_pending)
55 qc = alloc(sizeof(struct queued_chunk));
56 cq->num_pending += num_bytes;
58 qc->num_bytes = num_bytes;
59 list_add_tail(&qc->node, &cq->q);
60 PARA_DEBUG_LOG("%lu bytes queued for %p\n", cq->num_pending, &cq->q);
65 * Lookup the next chunk in the queue.
67 * \param cq The chunk queue.
69 * \return The next queued chunk, or \p NULL if there is no chunk available.
71 struct queued_chunk *cq_peek(struct chunk_queue *cq)
73 if (list_empty(&cq->q))
75 return list_entry(cq->q.next, struct queued_chunk, node);
79 * Remove the current chunk from the queue.
81 * \param cq The queue to remove from.
83 void cq_dequeue(struct chunk_queue *cq)
85 struct queued_chunk *qc = cq_peek(cq);
87 assert(cq->num_pending >= qc->num_bytes);
88 cq->num_pending -= qc->num_bytes;
94 * Change the number of bytes sent for the current queued chunk.
96 * \param cq The chunk queue.
97 * \param sent Number of bytes successfully sent.
99 void cq_update(struct chunk_queue *cq, size_t sent)
101 struct queued_chunk *qc = cq_peek(cq);
103 qc->num_bytes -= sent;
105 cq->num_pending -= sent;
109 * Get a pointer to the given queued chunk.
111 * \param qc The queued chunk.
112 * \param buf Result pointer.
113 * \param num_bytes Number of bytes of \a buf.
115 * \return Positive on success, negative on errors.
117 int cq_get(struct queued_chunk *qc, const char **buf, size_t *num_bytes)
120 *num_bytes = qc->num_bytes;
125 * Allocate and initialize a chunk queue.
127 * \param max_pending Maximal number of bytes that will be queued.
129 * \return A pointer to the new queue.
131 struct chunk_queue *cq_new(size_t max_pending)
133 struct chunk_queue *cq = alloc(sizeof(*cq));
134 init_list_head(&cq->q);
135 cq->max_pending = max_pending;
141 * Deallocate all resources of this queue.
143 * \param cq The chunk queue.
145 void cq_destroy(struct chunk_queue *cq)
147 struct queued_chunk *qc, *tmp;
148 list_for_each_entry_safe(qc, tmp, &cq->q, node) {