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