1278307Srpaulo///////////////////////////////////////////////////////////////////////////////
2278307Srpaulo//
3278307Srpaulo/// \file       outqueue.h
4278307Srpaulo/// \brief      Output queue handling in multithreaded coding
5278307Srpaulo//
6278307Srpaulo//  Author:     Lasse Collin
7278307Srpaulo//
8278307Srpaulo//  This file has been put into the public domain.
9278307Srpaulo//  You can do whatever you want with this file.
10278307Srpaulo//
11278307Srpaulo///////////////////////////////////////////////////////////////////////////////
12278307Srpaulo
13278307Srpaulo#include "common.h"
14278307Srpaulo
15278307Srpaulo
16278307Srpaulo/// Output buffer for a single thread
17278307Srpaulotypedef struct {
18278307Srpaulo	/// Pointer to the output buffer of lzma_outq.buf_size_max bytes
19278307Srpaulo	uint8_t *buf;
20278307Srpaulo
21278307Srpaulo	/// Amount of data written to buf
22278307Srpaulo	size_t size;
23278307Srpaulo
24278307Srpaulo	/// Additional size information
25278307Srpaulo	lzma_vli unpadded_size;
26278307Srpaulo	lzma_vli uncompressed_size;
27278307Srpaulo
28278307Srpaulo	/// True when no more data will be written into this buffer.
29278307Srpaulo	///
30278307Srpaulo	/// \note       This is read by another thread and thus access
31278307Srpaulo	///             to this variable needs a mutex.
32278307Srpaulo	bool finished;
33278307Srpaulo
34278307Srpaulo} lzma_outbuf;
35278307Srpaulo
36278307Srpaulo
37278307Srpaulotypedef struct {
38278307Srpaulo	/// Array of buffers that are used cyclically.
39278307Srpaulo	lzma_outbuf *bufs;
40278307Srpaulo
41278307Srpaulo	/// Memory allocated for all the buffers
42278307Srpaulo	uint8_t *bufs_mem;
43278307Srpaulo
44278307Srpaulo	/// Amount of buffer space available in each buffer
45278307Srpaulo	size_t buf_size_max;
46278307Srpaulo
47278307Srpaulo	/// Number of buffers allocated
48278307Srpaulo	uint32_t bufs_allocated;
49278307Srpaulo
50278307Srpaulo	/// Position in the bufs array. The next buffer to be taken
51278307Srpaulo	/// into use is bufs[bufs_pos].
52278307Srpaulo	uint32_t bufs_pos;
53278307Srpaulo
54278307Srpaulo	/// Number of buffers in use
55278307Srpaulo	uint32_t bufs_used;
56278307Srpaulo
57278307Srpaulo	/// Position in the buffer in lzma_outq_read()
58278307Srpaulo	size_t read_pos;
59278307Srpaulo
60278307Srpaulo} lzma_outq;
61278307Srpaulo
62278307Srpaulo
63278307Srpaulo/**
64278307Srpaulo * \brief       Calculate the memory usage of an output queue
65278307Srpaulo *
66278307Srpaulo * \return      Approximate memory usage in bytes or UINT64_MAX on error.
67278307Srpaulo */
68278307Srpauloextern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
69278307Srpaulo
70278307Srpaulo
71278307Srpaulo/// \brief      Initialize an output queue
72278307Srpaulo///
73278307Srpaulo/// \param      outq            Pointer to an output queue. Before calling
74278307Srpaulo///                             this function the first time, *outq should
75278307Srpaulo///                             have been zeroed with memzero() so that this
76278307Srpaulo///                             function knows that there are no previous
77278307Srpaulo///                             allocations to free.
78278307Srpaulo/// \param      allocator       Pointer to allocator or NULL
79278307Srpaulo/// \param      buf_size_max    Maximum amount of data that a single buffer
80278307Srpaulo///                             in the queue may need to store.
81278307Srpaulo/// \param      threads         Number of buffers that may be in use
82278307Srpaulo///                             concurrently. Note that more than this number
83278307Srpaulo///                             of buffers will actually get allocated to
84278307Srpaulo///                             improve performance when buffers finish
85278307Srpaulo///                             out of order.
86278307Srpaulo///
87278307Srpaulo/// \return     - LZMA_OK
88278307Srpaulo///             - LZMA_MEM_ERROR
89278307Srpaulo///
90278307Srpauloextern lzma_ret lzma_outq_init(
91278307Srpaulo		lzma_outq *outq, const lzma_allocator *allocator,
92278307Srpaulo		uint64_t buf_size_max, uint32_t threads);
93278307Srpaulo
94278307Srpaulo
95278307Srpaulo/// \brief      Free the memory associated with the output queue
96278307Srpauloextern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
97278307Srpaulo
98278307Srpaulo
99278307Srpaulo/// \brief      Get a new buffer
100278307Srpaulo///
101278307Srpaulo/// lzma_outq_has_buf() must be used to check that there is a buffer
102278307Srpaulo/// available before calling lzma_outq_get_buf().
103278307Srpaulo///
104278307Srpauloextern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
105278307Srpaulo
106278307Srpaulo
107278307Srpaulo/// \brief      Test if there is data ready to be read
108278307Srpaulo///
109278307Srpaulo/// Call to this function must be protected with the same mutex that
110278307Srpaulo/// is used to protect lzma_outbuf.finished.
111278307Srpaulo///
112278307Srpauloextern bool lzma_outq_is_readable(const lzma_outq *outq);
113278307Srpaulo
114278307Srpaulo
115278307Srpaulo/// \brief      Read finished data
116278307Srpaulo///
117278307Srpaulo/// \param      outq            Pointer to an output queue
118278307Srpaulo/// \param      out             Beginning of the output buffer
119278307Srpaulo/// \param      out_pos         The next byte will be written to
120278307Srpaulo///                             out[*out_pos].
121278307Srpaulo/// \param      out_size        Size of the out buffer; the first byte into
122278307Srpaulo///                             which no data is written to is out[out_size].
123278307Srpaulo/// \param      unpadded_size   Unpadded Size from the Block encoder
124278307Srpaulo/// \param      uncompressed_size Uncompressed Size from the Block encoder
125278307Srpaulo///
126278307Srpaulo/// \return     - LZMA: All OK. Either no data was available or the buffer
127278307Srpaulo///               being read didn't become empty yet.
128278307Srpaulo///             - LZMA_STREAM_END: The buffer being read was finished.
129278307Srpaulo///               *unpadded_size and *uncompressed_size were set.
130278307Srpaulo///
131278307Srpaulo/// \note       This reads lzma_outbuf.finished variables and thus call
132278307Srpaulo///             to this function needs to be protected with a mutex.
133278307Srpaulo///
134278307Srpauloextern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
135278307Srpaulo		uint8_t *restrict out, size_t *restrict out_pos,
136278307Srpaulo		size_t out_size, lzma_vli *restrict unpadded_size,
137278307Srpaulo		lzma_vli *restrict uncompressed_size);
138278307Srpaulo
139278307Srpaulo
140278307Srpaulo/// \brief      Test if there is at least one buffer free
141278307Srpaulo///
142278307Srpaulo/// This must be used before getting a new buffer with lzma_outq_get_buf().
143278307Srpaulo///
144278307Srpaulostatic inline bool
145278307Srpaulolzma_outq_has_buf(const lzma_outq *outq)
146278307Srpaulo{
147278307Srpaulo	return outq->bufs_used < outq->bufs_allocated;
148278307Srpaulo}
149278307Srpaulo
150278307Srpaulo
151278307Srpaulo/// \brief      Test if the queue is completely empty
152278307Srpaulostatic inline bool
153278307Srpaulolzma_outq_is_empty(const lzma_outq *outq)
154278307Srpaulo{
155278307Srpaulo	return outq->bufs_used == 0;
156278307Srpaulo}
157