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(<->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