liblzma: Add LZMA_FULL_BARRIER support to single-threaded encoder.

In the single-threaded encoder LZMA_FULL_BARRIER is simply
an alias for LZMA_FULL_FLUSH.
This commit is contained in:
Lasse Collin 2013-10-02 12:55:11 +03:00
parent fef0c6b410
commit 97bb38712f
4 changed files with 54 additions and 11 deletions

View File

@ -240,12 +240,12 @@ typedef enum {
/** /**
* \brief The `action' argument for lzma_code() * \brief The `action' argument for lzma_code()
* *
* After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH, * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
* the same `action' must is used until lzma_code() returns LZMA_STREAM_END. * or LZMA_FINISH, the same `action' must is used until lzma_code() returns
* Also, the amount of input (that is, strm->avail_in) must not be modified * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
* by the application until lzma_code() returns LZMA_STREAM_END. Changing the * not be modified by the application until lzma_code() returns
* `action' or modifying the amount of input will make lzma_code() return * LZMA_STREAM_END. Changing the `action' or modifying the amount of input
* LZMA_PROG_ERROR. * will make lzma_code() return LZMA_PROG_ERROR.
*/ */
typedef enum { typedef enum {
LZMA_RUN = 0, LZMA_RUN = 0,
@ -293,7 +293,7 @@ typedef enum {
* *
* All the input data going to the current Block must have * All the input data going to the current Block must have
* been given to the encoder (the last bytes can still be * been given to the encoder (the last bytes can still be
* pending in* next_in). Call lzma_code() with LZMA_FULL_FLUSH * pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH
* until it returns LZMA_STREAM_END. Then continue normally * until it returns LZMA_STREAM_END. Then continue normally
* with LZMA_RUN or finish the Stream with LZMA_FINISH. * with LZMA_RUN or finish the Stream with LZMA_FINISH.
* *
@ -302,6 +302,29 @@ typedef enum {
* no unfinished Block, no empty Block is created. * no unfinished Block, no empty Block is created.
*/ */
LZMA_FULL_BARRIER = 4,
/**<
* \brief Finish encoding of the current Block
*
* This is like LZMA_FULL_FLUSH except that this doesn't
* necessarily wait until all the input has been made
* available via the output buffer. That is, lzma_code()
* might return LZMA_STREAM_END as soon as all the input
* has been consumed (avail_in == 0).
*
* LZMA_FULL_BARRIER is useful with a threaded encoder if
* one wants to split the .xz Stream into Blocks at specific
* offsets but doesn't care if the output isn't flushed
* immediately. Using LZMA_FULL_BARRIER allows keeping
* the threads busy while LZMA_FULL_FLUSH would make
* lzma_code() wait until all the threads have finished
* until more data could be passed to the encoder.
*
* With a lzma_stream initialized with the single-threaded
* lzma_stream_encoder() or lzma_easy_encoder(),
* LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH.
*/
LZMA_FINISH = 3 LZMA_FINISH = 3
/**< /**<
* \brief Finish the coding operation * \brief Finish the coding operation

View File

@ -176,7 +176,7 @@ lzma_code(lzma_stream *strm, lzma_action action)
|| (strm->next_out == NULL && strm->avail_out != 0) || (strm->next_out == NULL && strm->avail_out != 0)
|| strm->internal == NULL || strm->internal == NULL
|| strm->internal->next.code == NULL || strm->internal->next.code == NULL
|| (unsigned int)(action) > LZMA_FINISH || (unsigned int)(action) > LZMA_ACTION_MAX
|| !strm->internal->supported_actions[action]) || !strm->internal->supported_actions[action])
return LZMA_PROG_ERROR; return LZMA_PROG_ERROR;
@ -211,6 +211,10 @@ lzma_code(lzma_stream *strm, lzma_action action)
case LZMA_FINISH: case LZMA_FINISH:
strm->internal->sequence = ISEQ_FINISH; strm->internal->sequence = ISEQ_FINISH;
break; break;
case LZMA_FULL_BARRIER:
strm->internal->sequence = ISEQ_FULL_BARRIER;
break;
} }
break; break;
@ -238,6 +242,13 @@ lzma_code(lzma_stream *strm, lzma_action action)
break; break;
case ISEQ_FULL_BARRIER:
if (action != LZMA_FULL_BARRIER
|| strm->internal->avail_in != strm->avail_in)
return LZMA_PROG_ERROR;
break;
case ISEQ_END: case ISEQ_END:
return LZMA_STREAM_END; return LZMA_STREAM_END;
@ -288,7 +299,9 @@ lzma_code(lzma_stream *strm, lzma_action action)
case LZMA_STREAM_END: case LZMA_STREAM_END:
if (strm->internal->sequence == ISEQ_SYNC_FLUSH if (strm->internal->sequence == ISEQ_SYNC_FLUSH
|| strm->internal->sequence == ISEQ_FULL_FLUSH) || strm->internal->sequence == ISEQ_FULL_FLUSH
|| strm->internal->sequence
== ISEQ_FULL_BARRIER)
strm->internal->sequence = ISEQ_RUN; strm->internal->sequence = ISEQ_RUN;
else else
strm->internal->sequence = ISEQ_END; strm->internal->sequence = ISEQ_END;

View File

@ -78,6 +78,10 @@
| LZMA_CONCATENATED ) | LZMA_CONCATENATED )
/// Largest valid lzma_action value as unsigned integer.
#define LZMA_ACTION_MAX ((unsigned int)(LZMA_FULL_BARRIER))
/// Special return value (lzma_ret) to indicate that a timeout was reached /// Special return value (lzma_ret) to indicate that a timeout was reached
/// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to /// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because /// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because
@ -207,6 +211,7 @@ struct lzma_internal_s {
ISEQ_SYNC_FLUSH, ISEQ_SYNC_FLUSH,
ISEQ_FULL_FLUSH, ISEQ_FULL_FLUSH,
ISEQ_FINISH, ISEQ_FINISH,
ISEQ_FULL_BARRIER,
ISEQ_END, ISEQ_END,
ISEQ_ERROR, ISEQ_ERROR,
} sequence; } sequence;
@ -217,7 +222,7 @@ struct lzma_internal_s {
size_t avail_in; size_t avail_in;
/// Indicates which lzma_action values are allowed by next.code. /// Indicates which lzma_action values are allowed by next.code.
bool supported_actions[4]; bool supported_actions[LZMA_ACTION_MAX + 1];
/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was /// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
/// made (no input consumed and no output produced by next.code). /// made (no input consumed and no output produced by next.code).

View File

@ -146,11 +146,12 @@ stream_encode(lzma_coder *coder, const lzma_allocator *allocator,
} }
case SEQ_BLOCK_ENCODE: { case SEQ_BLOCK_ENCODE: {
static const lzma_action convert[4] = { static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
LZMA_RUN, LZMA_RUN,
LZMA_SYNC_FLUSH, LZMA_SYNC_FLUSH,
LZMA_FINISH, LZMA_FINISH,
LZMA_FINISH, LZMA_FINISH,
LZMA_FINISH,
}; };
const lzma_ret ret = coder->block_encoder.code( const lzma_ret ret = coder->block_encoder.code(
@ -324,6 +325,7 @@ lzma_stream_encoder(lzma_stream *strm,
strm->internal->supported_actions[LZMA_RUN] = true; strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true; strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
strm->internal->supported_actions[LZMA_FINISH] = true; strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK; return LZMA_OK;