outqueue.h 4.9 KB

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