1370b324cSopenharmony_ci/* MtDec.h -- Multi-thread Decoder 2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci#ifndef ZIP7_INC_MT_DEC_H 5370b324cSopenharmony_ci#define ZIP7_INC_MT_DEC_H 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "7zTypes.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_ci#ifndef Z7_ST 10370b324cSopenharmony_ci#include "Threads.h" 11370b324cSopenharmony_ci#endif 12370b324cSopenharmony_ci 13370b324cSopenharmony_ciEXTERN_C_BEGIN 14370b324cSopenharmony_ci 15370b324cSopenharmony_ci#ifndef Z7_ST 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci#ifndef Z7_ST 18370b324cSopenharmony_ci #define MTDEC_THREADS_MAX 32 19370b324cSopenharmony_ci#else 20370b324cSopenharmony_ci #define MTDEC_THREADS_MAX 1 21370b324cSopenharmony_ci#endif 22370b324cSopenharmony_ci 23370b324cSopenharmony_ci 24370b324cSopenharmony_citypedef struct 25370b324cSopenharmony_ci{ 26370b324cSopenharmony_ci ICompressProgressPtr progress; 27370b324cSopenharmony_ci SRes res; 28370b324cSopenharmony_ci UInt64 totalInSize; 29370b324cSopenharmony_ci UInt64 totalOutSize; 30370b324cSopenharmony_ci CCriticalSection cs; 31370b324cSopenharmony_ci} CMtProgress; 32370b324cSopenharmony_ci 33370b324cSopenharmony_civoid MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress); 34370b324cSopenharmony_ciSRes MtProgress_Progress_ST(CMtProgress *p); 35370b324cSopenharmony_ciSRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); 36370b324cSopenharmony_ciSRes MtProgress_GetError(CMtProgress *p); 37370b324cSopenharmony_civoid MtProgress_SetError(CMtProgress *p, SRes res); 38370b324cSopenharmony_ci 39370b324cSopenharmony_cistruct CMtDec; 40370b324cSopenharmony_ci 41370b324cSopenharmony_citypedef struct 42370b324cSopenharmony_ci{ 43370b324cSopenharmony_ci struct CMtDec_ *mtDec; 44370b324cSopenharmony_ci unsigned index; 45370b324cSopenharmony_ci void *inBuf; 46370b324cSopenharmony_ci 47370b324cSopenharmony_ci size_t inDataSize_Start; // size of input data in start block 48370b324cSopenharmony_ci UInt64 inDataSize; // total size of input data in all blocks 49370b324cSopenharmony_ci 50370b324cSopenharmony_ci CThread thread; 51370b324cSopenharmony_ci CAutoResetEvent canRead; 52370b324cSopenharmony_ci CAutoResetEvent canWrite; 53370b324cSopenharmony_ci void *allocaPtr; 54370b324cSopenharmony_ci} CMtDecThread; 55370b324cSopenharmony_ci 56370b324cSopenharmony_civoid MtDecThread_FreeInBufs(CMtDecThread *t); 57370b324cSopenharmony_ci 58370b324cSopenharmony_ci 59370b324cSopenharmony_citypedef enum 60370b324cSopenharmony_ci{ 61370b324cSopenharmony_ci MTDEC_PARSE_CONTINUE, // continue this block with more input data 62370b324cSopenharmony_ci MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread 63370b324cSopenharmony_ci MTDEC_PARSE_NEW, // new block 64370b324cSopenharmony_ci MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) 65370b324cSopenharmony_ci} EMtDecParseState; 66370b324cSopenharmony_ci 67370b324cSopenharmony_citypedef struct 68370b324cSopenharmony_ci{ 69370b324cSopenharmony_ci // in 70370b324cSopenharmony_ci int startCall; 71370b324cSopenharmony_ci const Byte *src; 72370b324cSopenharmony_ci size_t srcSize; 73370b324cSopenharmony_ci // in : (srcSize == 0) is allowed 74370b324cSopenharmony_ci // out : it's allowed to return less that actually was used ? 75370b324cSopenharmony_ci int srcFinished; 76370b324cSopenharmony_ci 77370b324cSopenharmony_ci // out 78370b324cSopenharmony_ci EMtDecParseState state; 79370b324cSopenharmony_ci BoolInt canCreateNewThread; 80370b324cSopenharmony_ci UInt64 outPos; // check it (size_t) 81370b324cSopenharmony_ci} CMtDecCallbackInfo; 82370b324cSopenharmony_ci 83370b324cSopenharmony_ci 84370b324cSopenharmony_citypedef struct 85370b324cSopenharmony_ci{ 86370b324cSopenharmony_ci void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); 87370b324cSopenharmony_ci 88370b324cSopenharmony_ci // PreCode() and Code(): 89370b324cSopenharmony_ci // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks 90370b324cSopenharmony_ci SRes (*PreCode)(void *p, unsigned coderIndex); 91370b324cSopenharmony_ci SRes (*Code)(void *p, unsigned coderIndex, 92370b324cSopenharmony_ci const Byte *src, size_t srcSize, int srcFinished, 93370b324cSopenharmony_ci UInt64 *inCodePos, UInt64 *outCodePos, int *stop); 94370b324cSopenharmony_ci // stop - means stop another Code calls 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci 97370b324cSopenharmony_ci /* Write() must be called, if Parse() was called 98370b324cSopenharmony_ci set (needWrite) if 99370b324cSopenharmony_ci { 100370b324cSopenharmony_ci && (was not interrupted by progress) 101370b324cSopenharmony_ci && (was not interrupted in previous block) 102370b324cSopenharmony_ci } 103370b324cSopenharmony_ci 104370b324cSopenharmony_ci out: 105370b324cSopenharmony_ci if (*needContinue), decoder still need to continue decoding with new iteration, 106370b324cSopenharmony_ci even after MTDEC_PARSE_END 107370b324cSopenharmony_ci if (*canRecode), we didn't flush current block data, so we still can decode current block later. 108370b324cSopenharmony_ci */ 109370b324cSopenharmony_ci SRes (*Write)(void *p, unsigned coderIndex, 110370b324cSopenharmony_ci BoolInt needWriteToStream, 111370b324cSopenharmony_ci const Byte *src, size_t srcSize, BoolInt isCross, 112370b324cSopenharmony_ci // int srcFinished, 113370b324cSopenharmony_ci BoolInt *needContinue, 114370b324cSopenharmony_ci BoolInt *canRecode); 115370b324cSopenharmony_ci 116370b324cSopenharmony_ci} IMtDecCallback2; 117370b324cSopenharmony_ci 118370b324cSopenharmony_ci 119370b324cSopenharmony_ci 120370b324cSopenharmony_citypedef struct CMtDec_ 121370b324cSopenharmony_ci{ 122370b324cSopenharmony_ci /* input variables */ 123370b324cSopenharmony_ci 124370b324cSopenharmony_ci size_t inBufSize; /* size of input block */ 125370b324cSopenharmony_ci unsigned numThreadsMax; 126370b324cSopenharmony_ci // size_t inBlockMax; 127370b324cSopenharmony_ci unsigned numThreadsMax_2; 128370b324cSopenharmony_ci 129370b324cSopenharmony_ci ISeqInStreamPtr inStream; 130370b324cSopenharmony_ci // const Byte *inData; 131370b324cSopenharmony_ci // size_t inDataSize; 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci ICompressProgressPtr progress; 134370b324cSopenharmony_ci ISzAllocPtr alloc; 135370b324cSopenharmony_ci 136370b324cSopenharmony_ci IMtDecCallback2 *mtCallback; 137370b324cSopenharmony_ci void *mtCallbackObject; 138370b324cSopenharmony_ci 139370b324cSopenharmony_ci 140370b324cSopenharmony_ci /* internal variables */ 141370b324cSopenharmony_ci 142370b324cSopenharmony_ci size_t allocatedBufsSize; 143370b324cSopenharmony_ci 144370b324cSopenharmony_ci BoolInt exitThread; 145370b324cSopenharmony_ci WRes exitThreadWRes; 146370b324cSopenharmony_ci 147370b324cSopenharmony_ci UInt64 blockIndex; 148370b324cSopenharmony_ci BoolInt isAllocError; 149370b324cSopenharmony_ci BoolInt overflow; 150370b324cSopenharmony_ci SRes threadingErrorSRes; 151370b324cSopenharmony_ci 152370b324cSopenharmony_ci BoolInt needContinue; 153370b324cSopenharmony_ci 154370b324cSopenharmony_ci // CAutoResetEvent finishedEvent; 155370b324cSopenharmony_ci 156370b324cSopenharmony_ci SRes readRes; 157370b324cSopenharmony_ci SRes codeRes; 158370b324cSopenharmony_ci 159370b324cSopenharmony_ci BoolInt wasInterrupted; 160370b324cSopenharmony_ci 161370b324cSopenharmony_ci unsigned numStartedThreads_Limit; 162370b324cSopenharmony_ci unsigned numStartedThreads; 163370b324cSopenharmony_ci 164370b324cSopenharmony_ci Byte *crossBlock; 165370b324cSopenharmony_ci size_t crossStart; 166370b324cSopenharmony_ci size_t crossEnd; 167370b324cSopenharmony_ci UInt64 readProcessed; 168370b324cSopenharmony_ci BoolInt readWasFinished; 169370b324cSopenharmony_ci UInt64 inProcessed; 170370b324cSopenharmony_ci 171370b324cSopenharmony_ci unsigned filledThreadStart; 172370b324cSopenharmony_ci unsigned numFilledThreads; 173370b324cSopenharmony_ci 174370b324cSopenharmony_ci #ifndef Z7_ST 175370b324cSopenharmony_ci BoolInt needInterrupt; 176370b324cSopenharmony_ci UInt64 interruptIndex; 177370b324cSopenharmony_ci CMtProgress mtProgress; 178370b324cSopenharmony_ci CMtDecThread threads[MTDEC_THREADS_MAX]; 179370b324cSopenharmony_ci #endif 180370b324cSopenharmony_ci} CMtDec; 181370b324cSopenharmony_ci 182370b324cSopenharmony_ci 183370b324cSopenharmony_civoid MtDec_Construct(CMtDec *p); 184370b324cSopenharmony_civoid MtDec_Destruct(CMtDec *p); 185370b324cSopenharmony_ci 186370b324cSopenharmony_ci/* 187370b324cSopenharmony_ciMtDec_Code() returns: 188370b324cSopenharmony_ci SZ_OK - in most cases 189370b324cSopenharmony_ci MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function 190370b324cSopenharmony_ci*/ 191370b324cSopenharmony_ci 192370b324cSopenharmony_ciSRes MtDec_Code(CMtDec *p); 193370b324cSopenharmony_ciByte *MtDec_GetCrossBuff(CMtDec *p); 194370b324cSopenharmony_ci 195370b324cSopenharmony_ciint MtDec_PrepareRead(CMtDec *p); 196370b324cSopenharmony_ciconst Byte *MtDec_Read(CMtDec *p, size_t *inLim); 197370b324cSopenharmony_ci 198370b324cSopenharmony_ci#endif 199370b324cSopenharmony_ci 200370b324cSopenharmony_ciEXTERN_C_END 201370b324cSopenharmony_ci 202370b324cSopenharmony_ci#endif 203