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