outqueue.h revision 292588
1///////////////////////////////////////////////////////////////////////////////
2//
3/// \file       outqueue.h
4/// \brief      Output queue handling in multithreaded coding
5//
6//  Author:     Lasse Collin
7//
8//  This file has been put into the public domain.
9//  You can do whatever you want with this file.
10//
11///////////////////////////////////////////////////////////////////////////////
12
13#include "common.h"
14
15
16/// Output buffer for a single thread
17typedef struct {
18	/// Pointer to the output buffer of lzma_outq.buf_size_max bytes
19	uint8_t *buf;
20
21	/// Amount of data written to buf
22	size_t size;
23
24	/// Additional size information
25	lzma_vli unpadded_size;
26	lzma_vli uncompressed_size;
27
28	/// True when no more data will be written into this buffer.
29	///
30	/// \note       This is read by another thread and thus access
31	///             to this variable needs a mutex.
32	bool finished;
33
34} lzma_outbuf;
35
36
37typedef struct {
38	/// Array of buffers that are used cyclically.
39	lzma_outbuf *bufs;
40
41	/// Memory allocated for all the buffers
42	uint8_t *bufs_mem;
43
44	/// Amount of buffer space available in each buffer
45	size_t buf_size_max;
46
47	/// Number of buffers allocated
48	uint32_t bufs_allocated;
49
50	/// Position in the bufs array. The next buffer to be taken
51	/// into use is bufs[bufs_pos].
52	uint32_t bufs_pos;
53
54	/// Number of buffers in use
55	uint32_t bufs_used;
56
57	/// Position in the buffer in lzma_outq_read()
58	size_t read_pos;
59
60} lzma_outq;
61
62
63/**
64 * \brief       Calculate the memory usage of an output queue
65 *
66 * \return      Approximate memory usage in bytes or UINT64_MAX on error.
67 */
68extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
69
70
71/// \brief      Initialize an output queue
72///
73/// \param      outq            Pointer to an output queue. Before calling
74///                             this function the first time, *outq should
75///                             have been zeroed with memzero() so that this
76///                             function knows that there are no previous
77///                             allocations to free.
78/// \param      allocator       Pointer to allocator or NULL
79/// \param      buf_size_max    Maximum amount of data that a single buffer
80///                             in the queue may need to store.
81/// \param      threads         Number of buffers that may be in use
82///                             concurrently. Note that more than this number
83///                             of buffers will actually get allocated to
84///                             improve performance when buffers finish
85///                             out of order.
86///
87/// \return     - LZMA_OK
88///             - LZMA_MEM_ERROR
89///
90extern lzma_ret lzma_outq_init(
91		lzma_outq *outq, const lzma_allocator *allocator,
92		uint64_t buf_size_max, uint32_t threads);
93
94
95/// \brief      Free the memory associated with the output queue
96extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
97
98
99/// \brief      Get a new buffer
100///
101/// lzma_outq_has_buf() must be used to check that there is a buffer
102/// available before calling lzma_outq_get_buf().
103///
104extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
105
106
107/// \brief      Test if there is data ready to be read
108///
109/// Call to this function must be protected with the same mutex that
110/// is used to protect lzma_outbuf.finished.
111///
112extern bool lzma_outq_is_readable(const lzma_outq *outq);
113
114
115/// \brief      Read finished data
116///
117/// \param      outq            Pointer to an output queue
118/// \param      out             Beginning of the output buffer
119/// \param      out_pos         The next byte will be written to
120///                             out[*out_pos].
121/// \param      out_size        Size of the out buffer; the first byte into
122///                             which no data is written to is out[out_size].
123/// \param      unpadded_size   Unpadded Size from the Block encoder
124/// \param      uncompressed_size Uncompressed Size from the Block encoder
125///
126/// \return     - LZMA: All OK. Either no data was available or the buffer
127///               being read didn't become empty yet.
128///             - LZMA_STREAM_END: The buffer being read was finished.
129///               *unpadded_size and *uncompressed_size were set.
130///
131/// \note       This reads lzma_outbuf.finished variables and thus call
132///             to this function needs to be protected with a mutex.
133///
134extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
135		uint8_t *restrict out, size_t *restrict out_pos,
136		size_t out_size, lzma_vli *restrict unpadded_size,
137		lzma_vli *restrict uncompressed_size);
138
139
140/// \brief      Test if there is at least one buffer free
141///
142/// This must be used before getting a new buffer with lzma_outq_get_buf().
143///
144static inline bool
145lzma_outq_has_buf(const lzma_outq *outq)
146{
147	return outq->bufs_used < outq->bufs_allocated;
148}
149
150
151/// \brief      Test if the queue is completely empty
152static inline bool
153lzma_outq_is_empty(const lzma_outq *outq)
154{
155	return outq->bufs_used == 0;
156}
157