mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-12 21:52:12 +00:00
4497d7fdaa
As a bonus, add support for XZ-compressed files in ZIP
202 lines
4.3 KiB
C
202 lines
4.3 KiB
C
/* MtDec.h -- Multi-thread Decoder
|
|
2023-04-02 : Igor Pavlov : Public domain */
|
|
|
|
#ifndef ZIP7_INC_MT_DEC_H
|
|
#define ZIP7_INC_MT_DEC_H
|
|
|
|
#include "7zTypes.h"
|
|
|
|
#ifndef Z7_ST
|
|
#include "Threads.h"
|
|
#endif
|
|
|
|
EXTERN_C_BEGIN
|
|
|
|
#ifndef Z7_ST
|
|
|
|
#ifndef Z7_ST
|
|
#define MTDEC_THREADS_MAX 32
|
|
#else
|
|
#define MTDEC_THREADS_MAX 1
|
|
#endif
|
|
|
|
|
|
typedef struct
|
|
{
|
|
ICompressProgressPtr progress;
|
|
SRes res;
|
|
UInt64 totalInSize;
|
|
UInt64 totalOutSize;
|
|
CCriticalSection cs;
|
|
} CMtProgress;
|
|
|
|
void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress);
|
|
SRes MtProgress_Progress_ST(CMtProgress *p);
|
|
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
|
|
SRes MtProgress_GetError(CMtProgress *p);
|
|
void MtProgress_SetError(CMtProgress *p, SRes res);
|
|
|
|
struct CMtDec;
|
|
|
|
typedef struct
|
|
{
|
|
struct CMtDec_ *mtDec;
|
|
unsigned index;
|
|
void *inBuf;
|
|
|
|
size_t inDataSize_Start; // size of input data in start block
|
|
UInt64 inDataSize; // total size of input data in all blocks
|
|
|
|
CThread thread;
|
|
CAutoResetEvent canRead;
|
|
CAutoResetEvent canWrite;
|
|
void *allocaPtr;
|
|
} CMtDecThread;
|
|
|
|
void MtDecThread_FreeInBufs(CMtDecThread *t);
|
|
|
|
|
|
typedef enum
|
|
{
|
|
MTDEC_PARSE_CONTINUE, // continue this block with more input data
|
|
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
|
|
MTDEC_PARSE_NEW, // new block
|
|
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
|
|
} EMtDecParseState;
|
|
|
|
typedef struct
|
|
{
|
|
// in
|
|
int startCall;
|
|
const Byte *src;
|
|
size_t srcSize;
|
|
// in : (srcSize == 0) is allowed
|
|
// out : it's allowed to return less that actually was used ?
|
|
int srcFinished;
|
|
|
|
// out
|
|
EMtDecParseState state;
|
|
BoolInt canCreateNewThread;
|
|
UInt64 outPos; // check it (size_t)
|
|
} CMtDecCallbackInfo;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
|
|
|
|
// PreCode() and Code():
|
|
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
|
|
SRes (*PreCode)(void *p, unsigned coderIndex);
|
|
SRes (*Code)(void *p, unsigned coderIndex,
|
|
const Byte *src, size_t srcSize, int srcFinished,
|
|
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
|
|
// stop - means stop another Code calls
|
|
|
|
|
|
/* Write() must be called, if Parse() was called
|
|
set (needWrite) if
|
|
{
|
|
&& (was not interrupted by progress)
|
|
&& (was not interrupted in previous block)
|
|
}
|
|
|
|
out:
|
|
if (*needContinue), decoder still need to continue decoding with new iteration,
|
|
even after MTDEC_PARSE_END
|
|
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
|
|
*/
|
|
SRes (*Write)(void *p, unsigned coderIndex,
|
|
BoolInt needWriteToStream,
|
|
const Byte *src, size_t srcSize, BoolInt isCross,
|
|
// int srcFinished,
|
|
BoolInt *needContinue,
|
|
BoolInt *canRecode);
|
|
|
|
} IMtDecCallback2;
|
|
|
|
|
|
|
|
typedef struct CMtDec_
|
|
{
|
|
/* input variables */
|
|
|
|
size_t inBufSize; /* size of input block */
|
|
unsigned numThreadsMax;
|
|
// size_t inBlockMax;
|
|
unsigned numThreadsMax_2;
|
|
|
|
ISeqInStreamPtr inStream;
|
|
// const Byte *inData;
|
|
// size_t inDataSize;
|
|
|
|
ICompressProgressPtr progress;
|
|
ISzAllocPtr alloc;
|
|
|
|
IMtDecCallback2 *mtCallback;
|
|
void *mtCallbackObject;
|
|
|
|
|
|
/* internal variables */
|
|
|
|
size_t allocatedBufsSize;
|
|
|
|
BoolInt exitThread;
|
|
WRes exitThreadWRes;
|
|
|
|
UInt64 blockIndex;
|
|
BoolInt isAllocError;
|
|
BoolInt overflow;
|
|
SRes threadingErrorSRes;
|
|
|
|
BoolInt needContinue;
|
|
|
|
// CAutoResetEvent finishedEvent;
|
|
|
|
SRes readRes;
|
|
SRes codeRes;
|
|
|
|
BoolInt wasInterrupted;
|
|
|
|
unsigned numStartedThreads_Limit;
|
|
unsigned numStartedThreads;
|
|
|
|
Byte *crossBlock;
|
|
size_t crossStart;
|
|
size_t crossEnd;
|
|
UInt64 readProcessed;
|
|
BoolInt readWasFinished;
|
|
UInt64 inProcessed;
|
|
|
|
unsigned filledThreadStart;
|
|
unsigned numFilledThreads;
|
|
|
|
#ifndef Z7_ST
|
|
BoolInt needInterrupt;
|
|
UInt64 interruptIndex;
|
|
CMtProgress mtProgress;
|
|
CMtDecThread threads[MTDEC_THREADS_MAX];
|
|
#endif
|
|
} CMtDec;
|
|
|
|
|
|
void MtDec_Construct(CMtDec *p);
|
|
void MtDec_Destruct(CMtDec *p);
|
|
|
|
/*
|
|
MtDec_Code() returns:
|
|
SZ_OK - in most cases
|
|
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
|
|
*/
|
|
|
|
SRes MtDec_Code(CMtDec *p);
|
|
Byte *MtDec_GetCrossBuff(CMtDec *p);
|
|
|
|
int MtDec_PrepareRead(CMtDec *p);
|
|
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
|
|
|
|
#endif
|
|
|
|
EXTERN_C_END
|
|
|
|
#endif
|