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 17 typedef 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 37 typedef 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 */ 68 extern 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 /// 90 extern 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 96 extern 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 /// 104 extern 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 /// 112 extern 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 /// 134 extern 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 /// 144 static inline bool 145 lzma_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 152 static inline bool 153 lzma_outq_is_empty(const lzma_outq *outq) 154 { 155 return outq->bufs_used == 0; 156 } 157