2 * Copyright (C) 2007-2010 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file chunk_queue.c Queuing functions for paraslash senders. */
19 * Senders may use the chunk queue facility to deal with laggy connections. It
20 * allows them to enqueue chunks if they can not be sent out immediately.
22 * Chunk queues are "cheap" in the sense that only reference to the audio file
23 * data is stored, but not the data itself.
26 /** The list of pending chunks for this client. */
28 /** The number of pending bytes for this client. */
29 unsigned long num_pending
;
30 /** More than that many bytes in the queue is considered an error. */
31 unsigned long max_pending
;
34 /** Describes one queued chunk in a chunk queue. */
36 /** Pointer to the data to be queued. */
38 /** The number of bytes of this chunk. */
40 /** Position of the chunk in the chunk queue. */
41 struct list_head node
;
45 * Add a chunk to the given queue.
47 * \param cq the queue to add the chunk to.
48 * \param buf Pointer to the data to be queued.
49 * \param num_bytes The size of \a buf.
53 int cq_enqueue(struct chunk_queue
*cq
, const char *buf
, size_t num_bytes
)
55 struct queued_chunk
*qc
;
57 if (cq
->num_pending
+ num_bytes
> cq
->max_pending
)
59 qc
= para_malloc(sizeof(struct queued_chunk
));
60 cq
->num_pending
+= num_bytes
;
62 qc
->num_bytes
= num_bytes
;
63 list_add_tail(&qc
->node
, &cq
->q
);
64 PARA_DEBUG_LOG("%lu bytes queued for %p\n", cq
->num_pending
, &cq
->q
);
69 * Lookup the next chunk in the queue.
71 * \param cq The chunk queue.
73 * \return The next queued chunk, or \p NULL if there is no chunk available.
75 struct queued_chunk
*cq_peek(struct chunk_queue
*cq
)
77 if (list_empty(&cq
->q
))
79 return list_entry(cq
->q
.next
, struct queued_chunk
, node
);
83 * Remove the current chunk from the queue.
85 * \param cq The queue to remove from.
87 void cq_dequeue(struct chunk_queue
*cq
)
89 struct queued_chunk
*qc
= cq_peek(cq
);
91 assert(cq
->num_pending
>= qc
->num_bytes
);
92 cq
->num_pending
-= qc
->num_bytes
;
98 * Force to add a chunk to the given queue.
100 * \param cq See \ref cq_enqueue.
101 * \param buf See \ref cq_enqueue.
102 * \param num_bytes See \ref cq_enqueue.
104 * If queuing the given buffer would result in exceeding the maximal queue
105 * size, buffers are dropped from the beginning of the queue. Note that this
106 * function still might fail.
110 int cq_force_enqueue(struct chunk_queue
*cq
, const char *buf
, size_t num_bytes
)
114 if (num_bytes
> cq
->max_pending
)
117 ret
= cq_enqueue(cq
, buf
, num_bytes
);
126 * Change the number of bytes sent for the current queued chunk.
128 * \param cq The chunk queue.
129 * \param sent Number of bytes successfully sent.
131 void cq_update(struct chunk_queue
*cq
, size_t sent
)
133 struct queued_chunk
*qc
= cq_peek(cq
);
135 qc
->num_bytes
-= sent
;
137 cq
->num_pending
-= sent
;
141 * Get a pointer to the given queued chunk.
143 * \param qc The queued chunk.
144 * \param buf Result pointer.
145 * \param num_bytes Number of bytes of \a buf.
147 * \return Positive on success, negative on errors.
149 int cq_get(struct queued_chunk
*qc
, const char **buf
, size_t *num_bytes
)
152 *num_bytes
= qc
->num_bytes
;
157 * Allocate and initialize a chunk queue.
159 * \param max_pending Maximal number of bytes that will be queued.
161 * \return A pointer to the new queue.
163 struct chunk_queue
*cq_new(size_t max_pending
)
165 struct chunk_queue
*cq
= para_malloc(sizeof(*cq
));
166 INIT_LIST_HEAD(&cq
->q
);
167 cq
->max_pending
= max_pending
;
173 * Deallocate all resources of this queue.
175 * \param cq The chunk queue.
177 void cq_destroy(struct chunk_queue
*cq
)
179 struct queued_chunk
*qc
, *tmp
;
180 list_for_each_entry_safe(qc
, tmp
, &cq
->q
, node
) {