1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* MtCoder.c -- Multi-thread Coder
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync2010-09-24 : Igor Pavlov : Public domain */
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <stdio.h>
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "MtCoder.h"
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
8baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid LoopThread_Construct(CLoopThread *p)
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Thread_Construct(&p->thread);
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Construct(&p->startEvent);
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Construct(&p->finishedEvent);
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid LoopThread_Close(CLoopThread *p)
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Thread_Close(&p->thread);
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Close(&p->startEvent);
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Close(&p->finishedEvent);
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
22baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CLoopThread *p = (CLoopThread *)pp;
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Event_Wait(&p->startEvent) != 0)
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_THREAD;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->stop)
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return 0;
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->res = p->func(p->param);
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Event_Set(&p->finishedEvent) != 0)
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_THREAD;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
37baa3858d3f5d128a5c8466b700098109edcad5f2repo syncWRes LoopThread_Create(CLoopThread *p)
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->stop = 0;
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return Thread_Create(&p->thread, LoopThreadFunc, p);
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
45baa3858d3f5d128a5c8466b700098109edcad5f2repo syncWRes LoopThread_StopAndWait(CLoopThread *p)
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->stop = 1;
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Event_Set(&p->startEvent) != 0)
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return SZ_ERROR_THREAD;
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return Thread_Wait(&p->thread);
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
53baa3858d3f5d128a5c8466b700098109edcad5f2repo syncWRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
54baa3858d3f5d128a5c8466b700098109edcad5f2repo syncWRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
56baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
61baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  unsigned i;
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->inSizes[i] = p->outSizes[i] = 0;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->totalInSize = p->totalOutSize = 0;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->progress = progress;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->res = SZ_OK;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
71baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void MtProgress_Reinit(CMtProgress *p, unsigned index)
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->inSizes[index] = 0;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->outSizes[index] = 0;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define UPDATE_PROGRESS(size, prev, total) \
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
80baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SRes res;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Enter(&p->cs);
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->res == SZ_OK)
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  res = p->res;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Leave(&p->cs);
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
93baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void MtProgress_SetError(CMtProgress *p, SRes res)
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Enter(&p->cs);
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->res == SZ_OK)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->res = res;
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Leave(&p->cs);
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
101baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void MtCoder_SetError(CMtCoder* p, SRes res)
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Enter(&p->cs);
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->res == SZ_OK)
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    p->res = res;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Leave(&p->cs);
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* ---------- MtThread ---------- */
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
111baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->mtCoder = mtCoder;
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->outBuf = 0;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->inBuf = 0;
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Construct(&p->canRead);
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Construct(&p->canWrite);
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LoopThread_Construct(&p->thread);
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
123baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void CMtThread_CloseEvents(CMtThread *p)
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Close(&p->canRead);
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Event_Close(&p->canWrite);
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
129baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void CMtThread_Destruct(CMtThread *p)
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMtThread_CloseEvents(p);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Thread_WasCreated(&p->thread.thread))
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    LoopThread_StopAndWait(&p->thread);
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    LoopThread_Close(&p->thread);
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->mtCoder->alloc)
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IAlloc_Free(p->mtCoder->alloc, p->outBuf);
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->outBuf = 0;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->mtCoder->alloc)
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IAlloc_Free(p->mtCoder->alloc, p->inBuf);
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->inBuf = 0;
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define MY_BUF_ALLOC(buf, size, newSize) \
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (buf == 0 || size != newSize) \
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  { IAlloc_Free(p->mtCoder->alloc, buf); \
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (buf == 0) return SZ_ERROR_MEM; }
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
154baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic SRes CMtThread_Prepare(CMtThread *p)
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->stopReading = False;
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->stopWriting = False;
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SZ_OK;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
167baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t size = *processedSize;
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *processedSize = 0;
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (size != 0)
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t curSize = size;
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SRes res = stream->Read(stream, data, &curSize);
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize += curSize;
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    data += curSize;
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size -= curSize;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(res);
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (curSize == 0)
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_OK;
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return SZ_OK;
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads  - 1 ? 0 : p->index + 1]
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
187baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic SRes MtThread_Process(CMtThread *p, Bool *stop)
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMtThread *next;
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *stop = True;
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Event_Wait(&p->canRead) != 0)
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return SZ_ERROR_THREAD;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  next = GET_NEXT_THREAD(p);
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (p->stopReading)
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    next->stopReading = True;
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t size = p->mtCoder->blockSize;
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t destSize = p->outBufSize;
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    next->stopReading = *stop = (size != p->mtCoder->blockSize);
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Event_Set(&next->canRead) != 0)
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_THREAD;
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->outBuf, &destSize, p->inBuf, size, *stop));
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Event_Wait(&p->canWrite) != 0)
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_THREAD;
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->stopWriting)
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_FAIL;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return SZ_ERROR_WRITE;
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
226baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMtThread *p = (CMtThread *)pp;
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Bool stop;
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread *next = GET_NEXT_THREAD(p);
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SRes res = MtThread_Process(p, &stop);
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (res != SZ_OK)
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      MtCoder_SetError(p->mtCoder, res);
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      MtProgress_SetError(&p->mtCoder->mtProgress, res);
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      next->stopReading = True;
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      next->stopWriting = True;
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Event_Set(&next->canRead);
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Event_Set(&next->canWrite);
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return res;
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (stop)
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return 0;
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
249baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid MtCoder_Construct(CMtCoder* p)
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  unsigned i;
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->alloc = 0;
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread *t = &p->threads[i];
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    t->index = i;
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread_Construct(t, p);
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Init(&p->cs);
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Init(&p->mtProgress.cs);
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
263baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid MtCoder_Destruct(CMtCoder* p)
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  unsigned i;
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread_Destruct(&p->threads[i]);
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Delete(&p->cs);
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CriticalSection_Delete(&p->mtProgress.cs);
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
272baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSRes MtCoder_Code(CMtCoder *p)
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  unsigned i, numThreads = p->numThreads;
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SRes res = SZ_OK;
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->res = SZ_OK;
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MtProgress_Init(&p->mtProgress, p->progress);
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numThreads; i++)
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(CMtThread_Prepare(&p->threads[i]));
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numThreads; i++)
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread *t = &p->threads[i];
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CLoopThread *lt = &t->thread;
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!Thread_WasCreated(&lt->thread))
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      lt->func = ThreadFunc;
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      lt->param = t;
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (LoopThread_Create(lt) != SZ_OK)
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = SZ_ERROR_THREAD;
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == SZ_OK)
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    unsigned j;
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numThreads; i++)
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMtThread *t = &p->threads[i];
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        res = SZ_ERROR_THREAD;
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        p->threads[0].stopReading = True;
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Event_Set(&p->threads[0].canWrite);
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Event_Set(&p->threads[0].canRead);
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (j = 0; j < i; j++)
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      LoopThread_WaitSubThread(&p->threads[j].thread);
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numThreads; i++)
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMtThread_CloseEvents(&p->threads[i]);
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (res == SZ_OK) ? p->res : res;
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
328