static UInt32 NO_INLINE DecodeBlock(const CBlockProps &props, UInt32 *tt, COutBuffer &m_OutStream) { if (props.randMode) return DecodeBlock2Rand(tt, props.blockSize, props.origPtr, m_OutStream); else return DecodeBlock2 (tt, props.blockSize, props.origPtr, m_OutStream); }
void CState::ThreadFunc() { for (;;) { Decoder->CanProcessEvent.Lock(); Decoder->CS.Enter(); if (Decoder->CloseThreads) { Decoder->CS.Leave(); return; } if (Decoder->StreamWasFinished1) { FinishStream(); continue; } HRESULT res = S_OK; UInt32 blockIndex = Decoder->NextBlockIndex; UInt32 nextBlockIndex = blockIndex + 1; if (nextBlockIndex == Decoder->NumThreads) nextBlockIndex = 0; Decoder->NextBlockIndex = nextBlockIndex; UInt32 crc; UInt64 packSize; UInt32 blockSize = 0, origPtr = 0; bool randMode = false; try { bool wasFinished; res = Decoder->ReadSignatures(wasFinished, crc); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } if (wasFinished) { Decoder->Result1 = res; FinishStream(); continue; } res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax, Decoder->m_Selectors, Decoder->m_HuffmanDecoders, &blockSize, &origPtr, &randMode); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } packSize = Decoder->m_InStream.GetProcessedSize(); } catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } Decoder->CS.Leave(); DecodeBlock1(Counters, blockSize); bool needFinish = true; try { Decoder->m_States[blockIndex].CanWriteEvent.Lock(); needFinish = Decoder->StreamWasFinished2; if (!needFinish) { if ((randMode ? DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) : DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc) { if (Decoder->Progress) { UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize(); res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize); } } else res = S_FALSE; } } catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } if (res != S_OK) { Decoder->Result2 = res; Decoder->StreamWasFinished2 = true; } Decoder->m_States[nextBlockIndex].CanWriteEvent.Set(); if (res != S_OK || needFinish) { StreamWasFinishedEvent.Set(); Decoder->CanStartWaitingEvent.Lock(); WaitingWasStartedEvent.Set(); } } }
HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) { #ifdef COMPRESS_BZIP2_MT Progress = progress; RINOK(Create()); for (UInt32 t = 0; t < NumThreads; t++) { CState &s = m_States[t]; if (!s.Alloc()) return E_OUTOFMEMORY; if (MtMode) { RINOK(s.StreamWasFinishedEvent.Reset()); RINOK(s.WaitingWasStartedEvent.Reset()); RINOK(s.CanWriteEvent.Reset()); } } #else if (!m_States[0].Alloc()) return E_OUTOFMEMORY; #endif isBZ = false; Byte s[6]; int i; for (i = 0; i < 4; i++) s[i] = ReadByte(); if (s[0] != kArSig0 || s[1] != kArSig1 || s[2] != kArSig2 || s[3] <= kArSig3 || s[3] > kArSig3 + kBlockSizeMultMax) return S_OK; isBZ = true; UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; CombinedCrc.Init(); #ifdef COMPRESS_BZIP2_MT if (MtMode) { NextBlockIndex = 0; StreamWasFinished1 = StreamWasFinished2 = false; CloseThreads = false; CanStartWaitingEvent.Reset(); m_States[0].CanWriteEvent.Set(); BlockSizeMax = dicSize; Result1 = Result2 = S_OK; CanProcessEvent.Set(); UInt32 t; for (t = 0; t < NumThreads; t++) m_States[t].StreamWasFinishedEvent.Lock(); CanProcessEvent.Reset(); CanStartWaitingEvent.Set(); for (t = 0; t < NumThreads; t++) m_States[t].WaitingWasStartedEvent.Lock(); CanStartWaitingEvent.Reset(); RINOK(Result2); RINOK(Result1); } else #endif { CState &state = m_States[0]; for (;;) { if (progress) { UInt64 packSize = m_InStream.GetProcessedSize(); UInt64 unpackSize = m_OutStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); } bool wasFinished; UInt32 crc; RINOK(ReadSignatures(wasFinished, crc)); if (wasFinished) return S_OK; UInt32 blockSize, origPtr; bool randMode; RINOK(ReadBlock(&m_InStream, state.Counters, dicSize, m_Selectors, m_HuffmanDecoders, &blockSize, &origPtr, &randMode)); DecodeBlock1(state.Counters, blockSize); if ((randMode ? DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) : DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc) return S_FALSE; } } return S_OK; }