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