]> pd.if.org Git - zpackage/blobdiff - lzma/common/outqueue.h
integrate lzma
[zpackage] / lzma / common / outqueue.h
diff --git a/lzma/common/outqueue.h b/lzma/common/outqueue.h
new file mode 100644 (file)
index 0000000..079634d
--- /dev/null
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       outqueue.h
+/// \brief      Output queue handling in multithreaded coding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/// Output buffer for a single thread
+typedef struct {
+       /// Pointer to the output buffer of lzma_outq.buf_size_max bytes
+       uint8_t *buf;
+
+       /// Amount of data written to buf
+       size_t size;
+
+       /// Additional size information
+       lzma_vli unpadded_size;
+       lzma_vli uncompressed_size;
+
+       /// True when no more data will be written into this buffer.
+       ///
+       /// \note       This is read by another thread and thus access
+       ///             to this variable needs a mutex.
+       bool finished;
+
+} lzma_outbuf;
+
+
+typedef struct {
+       /// Array of buffers that are used cyclically.
+       lzma_outbuf *bufs;
+
+       /// Memory allocated for all the buffers
+       uint8_t *bufs_mem;
+
+       /// Amount of buffer space available in each buffer
+       size_t buf_size_max;
+
+       /// Number of buffers allocated
+       uint32_t bufs_allocated;
+
+       /// Position in the bufs array. The next buffer to be taken
+       /// into use is bufs[bufs_pos].
+       uint32_t bufs_pos;
+
+       /// Number of buffers in use
+       uint32_t bufs_used;
+
+       /// Position in the buffer in lzma_outq_read()
+       size_t read_pos;
+
+} lzma_outq;
+
+
+/**
+ * \brief       Calculate the memory usage of an output queue
+ *
+ * \return      Approximate memory usage in bytes or UINT64_MAX on error.
+ */
+extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief      Initialize an output queue
+///
+/// \param      outq            Pointer to an output queue. Before calling
+///                             this function the first time, *outq should
+///                             have been zeroed with memzero() so that this
+///                             function knows that there are no previous
+///                             allocations to free.
+/// \param      allocator       Pointer to allocator or NULL
+/// \param      buf_size_max    Maximum amount of data that a single buffer
+///                             in the queue may need to store.
+/// \param      threads         Number of buffers that may be in use
+///                             concurrently. Note that more than this number
+///                             of buffers will actually get allocated to
+///                             improve performance when buffers finish
+///                             out of order.
+///
+/// \return     - LZMA_OK
+///             - LZMA_MEM_ERROR
+///
+extern lzma_ret lzma_outq_init(
+               lzma_outq *outq, const lzma_allocator *allocator,
+               uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief      Free the memory associated with the output queue
+extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
+
+
+/// \brief      Get a new buffer
+///
+/// lzma_outq_has_buf() must be used to check that there is a buffer
+/// available before calling lzma_outq_get_buf().
+///
+extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
+
+
+/// \brief      Test if there is data ready to be read
+///
+/// Call to this function must be protected with the same mutex that
+/// is used to protect lzma_outbuf.finished.
+///
+extern bool lzma_outq_is_readable(const lzma_outq *outq);
+
+
+/// \brief      Read finished data
+///
+/// \param      outq            Pointer to an output queue
+/// \param      out             Beginning of the output buffer
+/// \param      out_pos         The next byte will be written to
+///                             out[*out_pos].
+/// \param      out_size        Size of the out buffer; the first byte into
+///                             which no data is written to is out[out_size].
+/// \param      unpadded_size   Unpadded Size from the Block encoder
+/// \param      uncompressed_size Uncompressed Size from the Block encoder
+///
+/// \return     - LZMA: All OK. Either no data was available or the buffer
+///               being read didn't become empty yet.
+///             - LZMA_STREAM_END: The buffer being read was finished.
+///               *unpadded_size and *uncompressed_size were set.
+///
+/// \note       This reads lzma_outbuf.finished variables and thus call
+///             to this function needs to be protected with a mutex.
+///
+extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
+               uint8_t *restrict out, size_t *restrict out_pos,
+               size_t out_size, lzma_vli *restrict unpadded_size,
+               lzma_vli *restrict uncompressed_size);
+
+
+/// \brief      Test if there is at least one buffer free
+///
+/// This must be used before getting a new buffer with lzma_outq_get_buf().
+///
+static inline bool
+lzma_outq_has_buf(const lzma_outq *outq)
+{
+       return outq->bufs_used < outq->bufs_allocated;
+}
+
+
+/// \brief      Test if the queue is completely empty
+static inline bool
+lzma_outq_is_empty(const lzma_outq *outq)
+{
+       return outq->bufs_used == 0;
+}