1*f6dc9357SAndroid Build Coastguard Worker /* MtDec.h -- Multi-thread Decoder 2*f6dc9357SAndroid Build Coastguard Worker 2023-04-02 : Igor Pavlov : Public domain */ 3*f6dc9357SAndroid Build Coastguard Worker 4*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_MT_DEC_H 5*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_MT_DEC_H 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "7zTypes.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 10*f6dc9357SAndroid Build Coastguard Worker #include "Threads.h" 11*f6dc9357SAndroid Build Coastguard Worker #endif 12*f6dc9357SAndroid Build Coastguard Worker 13*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN 14*f6dc9357SAndroid Build Coastguard Worker 15*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 16*f6dc9357SAndroid Build Coastguard Worker 17*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 18*f6dc9357SAndroid Build Coastguard Worker #define MTDEC_THREADS_MAX 32 19*f6dc9357SAndroid Build Coastguard Worker #else 20*f6dc9357SAndroid Build Coastguard Worker #define MTDEC_THREADS_MAX 1 21*f6dc9357SAndroid Build Coastguard Worker #endif 22*f6dc9357SAndroid Build Coastguard Worker 23*f6dc9357SAndroid Build Coastguard Worker 24*f6dc9357SAndroid Build Coastguard Worker typedef struct 25*f6dc9357SAndroid Build Coastguard Worker { 26*f6dc9357SAndroid Build Coastguard Worker ICompressProgressPtr progress; 27*f6dc9357SAndroid Build Coastguard Worker SRes res; 28*f6dc9357SAndroid Build Coastguard Worker UInt64 totalInSize; 29*f6dc9357SAndroid Build Coastguard Worker UInt64 totalOutSize; 30*f6dc9357SAndroid Build Coastguard Worker CCriticalSection cs; 31*f6dc9357SAndroid Build Coastguard Worker } CMtProgress; 32*f6dc9357SAndroid Build Coastguard Worker 33*f6dc9357SAndroid Build Coastguard Worker void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress); 34*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_Progress_ST(CMtProgress *p); 35*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); 36*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_GetError(CMtProgress *p); 37*f6dc9357SAndroid Build Coastguard Worker void MtProgress_SetError(CMtProgress *p, SRes res); 38*f6dc9357SAndroid Build Coastguard Worker 39*f6dc9357SAndroid Build Coastguard Worker struct CMtDec; 40*f6dc9357SAndroid Build Coastguard Worker 41*f6dc9357SAndroid Build Coastguard Worker typedef struct 42*f6dc9357SAndroid Build Coastguard Worker { 43*f6dc9357SAndroid Build Coastguard Worker struct CMtDec_ *mtDec; 44*f6dc9357SAndroid Build Coastguard Worker unsigned index; 45*f6dc9357SAndroid Build Coastguard Worker void *inBuf; 46*f6dc9357SAndroid Build Coastguard Worker 47*f6dc9357SAndroid Build Coastguard Worker size_t inDataSize_Start; // size of input data in start block 48*f6dc9357SAndroid Build Coastguard Worker UInt64 inDataSize; // total size of input data in all blocks 49*f6dc9357SAndroid Build Coastguard Worker 50*f6dc9357SAndroid Build Coastguard Worker CThread thread; 51*f6dc9357SAndroid Build Coastguard Worker CAutoResetEvent canRead; 52*f6dc9357SAndroid Build Coastguard Worker CAutoResetEvent canWrite; 53*f6dc9357SAndroid Build Coastguard Worker void *allocaPtr; 54*f6dc9357SAndroid Build Coastguard Worker } CMtDecThread; 55*f6dc9357SAndroid Build Coastguard Worker 56*f6dc9357SAndroid Build Coastguard Worker void MtDecThread_FreeInBufs(CMtDecThread *t); 57*f6dc9357SAndroid Build Coastguard Worker 58*f6dc9357SAndroid Build Coastguard Worker 59*f6dc9357SAndroid Build Coastguard Worker typedef enum 60*f6dc9357SAndroid Build Coastguard Worker { 61*f6dc9357SAndroid Build Coastguard Worker MTDEC_PARSE_CONTINUE, // continue this block with more input data 62*f6dc9357SAndroid Build Coastguard Worker MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread 63*f6dc9357SAndroid Build Coastguard Worker MTDEC_PARSE_NEW, // new block 64*f6dc9357SAndroid Build Coastguard Worker MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) 65*f6dc9357SAndroid Build Coastguard Worker } EMtDecParseState; 66*f6dc9357SAndroid Build Coastguard Worker 67*f6dc9357SAndroid Build Coastguard Worker typedef struct 68*f6dc9357SAndroid Build Coastguard Worker { 69*f6dc9357SAndroid Build Coastguard Worker // in 70*f6dc9357SAndroid Build Coastguard Worker int startCall; 71*f6dc9357SAndroid Build Coastguard Worker const Byte *src; 72*f6dc9357SAndroid Build Coastguard Worker size_t srcSize; 73*f6dc9357SAndroid Build Coastguard Worker // in : (srcSize == 0) is allowed 74*f6dc9357SAndroid Build Coastguard Worker // out : it's allowed to return less that actually was used ? 75*f6dc9357SAndroid Build Coastguard Worker int srcFinished; 76*f6dc9357SAndroid Build Coastguard Worker 77*f6dc9357SAndroid Build Coastguard Worker // out 78*f6dc9357SAndroid Build Coastguard Worker EMtDecParseState state; 79*f6dc9357SAndroid Build Coastguard Worker BoolInt canCreateNewThread; 80*f6dc9357SAndroid Build Coastguard Worker UInt64 outPos; // check it (size_t) 81*f6dc9357SAndroid Build Coastguard Worker } CMtDecCallbackInfo; 82*f6dc9357SAndroid Build Coastguard Worker 83*f6dc9357SAndroid Build Coastguard Worker 84*f6dc9357SAndroid Build Coastguard Worker typedef struct 85*f6dc9357SAndroid Build Coastguard Worker { 86*f6dc9357SAndroid Build Coastguard Worker void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); 87*f6dc9357SAndroid Build Coastguard Worker 88*f6dc9357SAndroid Build Coastguard Worker // PreCode() and Code(): 89*f6dc9357SAndroid Build Coastguard Worker // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks 90*f6dc9357SAndroid Build Coastguard Worker SRes (*PreCode)(void *p, unsigned coderIndex); 91*f6dc9357SAndroid Build Coastguard Worker SRes (*Code)(void *p, unsigned coderIndex, 92*f6dc9357SAndroid Build Coastguard Worker const Byte *src, size_t srcSize, int srcFinished, 93*f6dc9357SAndroid Build Coastguard Worker UInt64 *inCodePos, UInt64 *outCodePos, int *stop); 94*f6dc9357SAndroid Build Coastguard Worker // stop - means stop another Code calls 95*f6dc9357SAndroid Build Coastguard Worker 96*f6dc9357SAndroid Build Coastguard Worker 97*f6dc9357SAndroid Build Coastguard Worker /* Write() must be called, if Parse() was called 98*f6dc9357SAndroid Build Coastguard Worker set (needWrite) if 99*f6dc9357SAndroid Build Coastguard Worker { 100*f6dc9357SAndroid Build Coastguard Worker && (was not interrupted by progress) 101*f6dc9357SAndroid Build Coastguard Worker && (was not interrupted in previous block) 102*f6dc9357SAndroid Build Coastguard Worker } 103*f6dc9357SAndroid Build Coastguard Worker 104*f6dc9357SAndroid Build Coastguard Worker out: 105*f6dc9357SAndroid Build Coastguard Worker if (*needContinue), decoder still need to continue decoding with new iteration, 106*f6dc9357SAndroid Build Coastguard Worker even after MTDEC_PARSE_END 107*f6dc9357SAndroid Build Coastguard Worker if (*canRecode), we didn't flush current block data, so we still can decode current block later. 108*f6dc9357SAndroid Build Coastguard Worker */ 109*f6dc9357SAndroid Build Coastguard Worker SRes (*Write)(void *p, unsigned coderIndex, 110*f6dc9357SAndroid Build Coastguard Worker BoolInt needWriteToStream, 111*f6dc9357SAndroid Build Coastguard Worker const Byte *src, size_t srcSize, BoolInt isCross, 112*f6dc9357SAndroid Build Coastguard Worker // int srcFinished, 113*f6dc9357SAndroid Build Coastguard Worker BoolInt *needContinue, 114*f6dc9357SAndroid Build Coastguard Worker BoolInt *canRecode); 115*f6dc9357SAndroid Build Coastguard Worker 116*f6dc9357SAndroid Build Coastguard Worker } IMtDecCallback2; 117*f6dc9357SAndroid Build Coastguard Worker 118*f6dc9357SAndroid Build Coastguard Worker 119*f6dc9357SAndroid Build Coastguard Worker 120*f6dc9357SAndroid Build Coastguard Worker typedef struct CMtDec_ 121*f6dc9357SAndroid Build Coastguard Worker { 122*f6dc9357SAndroid Build Coastguard Worker /* input variables */ 123*f6dc9357SAndroid Build Coastguard Worker 124*f6dc9357SAndroid Build Coastguard Worker size_t inBufSize; /* size of input block */ 125*f6dc9357SAndroid Build Coastguard Worker unsigned numThreadsMax; 126*f6dc9357SAndroid Build Coastguard Worker // size_t inBlockMax; 127*f6dc9357SAndroid Build Coastguard Worker unsigned numThreadsMax_2; 128*f6dc9357SAndroid Build Coastguard Worker 129*f6dc9357SAndroid Build Coastguard Worker ISeqInStreamPtr inStream; 130*f6dc9357SAndroid Build Coastguard Worker // const Byte *inData; 131*f6dc9357SAndroid Build Coastguard Worker // size_t inDataSize; 132*f6dc9357SAndroid Build Coastguard Worker 133*f6dc9357SAndroid Build Coastguard Worker ICompressProgressPtr progress; 134*f6dc9357SAndroid Build Coastguard Worker ISzAllocPtr alloc; 135*f6dc9357SAndroid Build Coastguard Worker 136*f6dc9357SAndroid Build Coastguard Worker IMtDecCallback2 *mtCallback; 137*f6dc9357SAndroid Build Coastguard Worker void *mtCallbackObject; 138*f6dc9357SAndroid Build Coastguard Worker 139*f6dc9357SAndroid Build Coastguard Worker 140*f6dc9357SAndroid Build Coastguard Worker /* internal variables */ 141*f6dc9357SAndroid Build Coastguard Worker 142*f6dc9357SAndroid Build Coastguard Worker size_t allocatedBufsSize; 143*f6dc9357SAndroid Build Coastguard Worker 144*f6dc9357SAndroid Build Coastguard Worker BoolInt exitThread; 145*f6dc9357SAndroid Build Coastguard Worker WRes exitThreadWRes; 146*f6dc9357SAndroid Build Coastguard Worker 147*f6dc9357SAndroid Build Coastguard Worker UInt64 blockIndex; 148*f6dc9357SAndroid Build Coastguard Worker BoolInt isAllocError; 149*f6dc9357SAndroid Build Coastguard Worker BoolInt overflow; 150*f6dc9357SAndroid Build Coastguard Worker SRes threadingErrorSRes; 151*f6dc9357SAndroid Build Coastguard Worker 152*f6dc9357SAndroid Build Coastguard Worker BoolInt needContinue; 153*f6dc9357SAndroid Build Coastguard Worker 154*f6dc9357SAndroid Build Coastguard Worker // CAutoResetEvent finishedEvent; 155*f6dc9357SAndroid Build Coastguard Worker 156*f6dc9357SAndroid Build Coastguard Worker SRes readRes; 157*f6dc9357SAndroid Build Coastguard Worker SRes codeRes; 158*f6dc9357SAndroid Build Coastguard Worker 159*f6dc9357SAndroid Build Coastguard Worker BoolInt wasInterrupted; 160*f6dc9357SAndroid Build Coastguard Worker 161*f6dc9357SAndroid Build Coastguard Worker unsigned numStartedThreads_Limit; 162*f6dc9357SAndroid Build Coastguard Worker unsigned numStartedThreads; 163*f6dc9357SAndroid Build Coastguard Worker 164*f6dc9357SAndroid Build Coastguard Worker Byte *crossBlock; 165*f6dc9357SAndroid Build Coastguard Worker size_t crossStart; 166*f6dc9357SAndroid Build Coastguard Worker size_t crossEnd; 167*f6dc9357SAndroid Build Coastguard Worker UInt64 readProcessed; 168*f6dc9357SAndroid Build Coastguard Worker BoolInt readWasFinished; 169*f6dc9357SAndroid Build Coastguard Worker UInt64 inProcessed; 170*f6dc9357SAndroid Build Coastguard Worker 171*f6dc9357SAndroid Build Coastguard Worker unsigned filledThreadStart; 172*f6dc9357SAndroid Build Coastguard Worker unsigned numFilledThreads; 173*f6dc9357SAndroid Build Coastguard Worker 174*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 175*f6dc9357SAndroid Build Coastguard Worker BoolInt needInterrupt; 176*f6dc9357SAndroid Build Coastguard Worker UInt64 interruptIndex; 177*f6dc9357SAndroid Build Coastguard Worker CMtProgress mtProgress; 178*f6dc9357SAndroid Build Coastguard Worker CMtDecThread threads[MTDEC_THREADS_MAX]; 179*f6dc9357SAndroid Build Coastguard Worker #endif 180*f6dc9357SAndroid Build Coastguard Worker } CMtDec; 181*f6dc9357SAndroid Build Coastguard Worker 182*f6dc9357SAndroid Build Coastguard Worker 183*f6dc9357SAndroid Build Coastguard Worker void MtDec_Construct(CMtDec *p); 184*f6dc9357SAndroid Build Coastguard Worker void MtDec_Destruct(CMtDec *p); 185*f6dc9357SAndroid Build Coastguard Worker 186*f6dc9357SAndroid Build Coastguard Worker /* 187*f6dc9357SAndroid Build Coastguard Worker MtDec_Code() returns: 188*f6dc9357SAndroid Build Coastguard Worker SZ_OK - in most cases 189*f6dc9357SAndroid Build Coastguard Worker MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function 190*f6dc9357SAndroid Build Coastguard Worker */ 191*f6dc9357SAndroid Build Coastguard Worker 192*f6dc9357SAndroid Build Coastguard Worker SRes MtDec_Code(CMtDec *p); 193*f6dc9357SAndroid Build Coastguard Worker Byte *MtDec_GetCrossBuff(CMtDec *p); 194*f6dc9357SAndroid Build Coastguard Worker 195*f6dc9357SAndroid Build Coastguard Worker int MtDec_PrepareRead(CMtDec *p); 196*f6dc9357SAndroid Build Coastguard Worker const Byte *MtDec_Read(CMtDec *p, size_t *inLim); 197*f6dc9357SAndroid Build Coastguard Worker 198*f6dc9357SAndroid Build Coastguard Worker #endif 199*f6dc9357SAndroid Build Coastguard Worker 200*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END 201*f6dc9357SAndroid Build Coastguard Worker 202*f6dc9357SAndroid Build Coastguard Worker #endif 203