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