?? mt.cpp
字號:
// MT.cpp#include "StdAfx.h"#include "../../../../Common/Alloc.h"#include "MT.h"static const UInt32 kBlockSize = (1 << 14);static DWORD WINAPI MFThread(void *threadCoderInfo){ return ((CMatchFinderMT *)threadCoderInfo)->ThreadFunc();}CMatchFinderMT::CMatchFinderMT(): m_Buffer(0), m_NeedStart(true){ m_BlockIndex = kNumMTBlocks - 1; m_CS[m_BlockIndex].Enter(); if (!m_Thread.Create(MFThread, this)) throw 271826;}CMatchFinderMT::~CMatchFinderMT() { m_Exit = true; m_CS[m_BlockIndex].Leave(); m_CanChangeBufferPos.Set(); if (m_NeedStart) m_MtCanStart.Set(); m_Thread.Wait(); FreeMem();}void CMatchFinderMT::FreeMem(){ ::MyFree(m_Buffer); m_Buffer = 0;}STDMETHODIMP CMatchFinderMT::Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter){ FreeMem(); m_MatchMaxLen = matchMaxLen; if (kBlockSize <= matchMaxLen * 4) return E_INVALIDARG; UInt32 bufferSize = kBlockSize * kNumMTBlocks; m_Buffer = (UInt32 *)::MyAlloc(bufferSize * sizeof(UInt32)); if (m_Buffer == 0) return E_OUTOFMEMORY; keepAddBufferBefore += bufferSize; keepAddBufferAfter += (kBlockSize + 1); return m_MatchFinder->Create(sizeHistory, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter); }// UInt32 blockSizeMult = 800HRESULT CMatchFinderMT::SetMatchFinder(IMatchFinder *matchFinder){ m_MatchFinder = matchFinder; return S_OK;}STDMETHODIMP CMatchFinderMT::SetStream(ISequentialInStream *s){ return m_MatchFinder->SetStream(s);}// Call it after ReleaseStream / SetStreamSTDMETHODIMP CMatchFinderMT::Init(){ m_NeedStart = true; m_Pos = 0; m_PosLimit = 0; HRESULT result = m_MatchFinder->Init(); if (result == S_OK) m_DataCurrentPos = m_MatchFinder->GetPointerToCurrentPos(); m_NumAvailableBytes = m_MatchFinder->GetNumAvailableBytes(); return result; }// ReleaseStream is required to finish multithreadingSTDMETHODIMP_(void) CMatchFinderMT::ReleaseStream(){ m_StopWriting = true; m_CS[m_BlockIndex].Leave(); if (!m_NeedStart) { m_CanChangeBufferPos.Set(); m_MtWasStopped.Lock(); m_NeedStart = true; } m_MatchFinder->ReleaseStream(); m_BlockIndex = kNumMTBlocks - 1; m_CS[m_BlockIndex].Enter();}STDMETHODIMP_(Byte) CMatchFinderMT::GetIndexByte(Int32 index){ return m_DataCurrentPos[index]; }STDMETHODIMP_(UInt32) CMatchFinderMT::GetMatchLen(Int32 index, UInt32 distance, UInt32 limit){ if ((Int32)(index + limit) > m_NumAvailableBytes) limit = m_NumAvailableBytes - (index); distance++; const Byte *pby1 = m_DataCurrentPos + index; const Byte *pby2 = pby1 - distance; // FIXED UInt32 i; for(i = 0; i < limit && pby1[i] == pby2[i]; i++); // FIXED return i;}STDMETHODIMP_(const Byte *) CMatchFinderMT::GetPointerToCurrentPos(){ return m_DataCurrentPos;}STDMETHODIMP_(UInt32) CMatchFinderMT::GetNumAvailableBytes(){ return m_NumAvailableBytes;} void CMatchFinderMT::GetNextBlock(){ if (m_NeedStart) { m_NeedStart = false; for (UInt32 i = 0; i < kNumMTBlocks; i++) m_StopReading[i] = false; m_StopWriting = false; m_Exit = false; m_MtWasStarted.Reset(); m_MtWasStopped.Reset(); m_CanChangeBufferPos.Reset(); m_BufferPosWasChanged.Reset(); m_MtCanStart.Set(); m_MtWasStarted.Lock(); m_Result = S_OK; } while (true) { UInt32 nextIndex = (m_BlockIndex == kNumMTBlocks - 1) ? 0 : m_BlockIndex + 1; m_CS[nextIndex].Enter(); if (!m_StopReading[nextIndex]) { m_CS[m_BlockIndex].Leave(); m_BlockIndex = nextIndex; break; } m_StopReading[nextIndex] = false; m_CS[nextIndex].Leave(); m_CanChangeBufferPos.Set(); m_BufferPosWasChanged.Lock(); m_CS[nextIndex].Enter(); m_CS[m_BlockIndex].Leave(); m_BlockIndex = nextIndex; } m_Pos = m_BlockIndex * kBlockSize; m_PosLimit = m_Buffer[m_Pos++]; m_NumAvailableBytes = m_Buffer[m_Pos++]; m_Result = m_Results[m_BlockIndex];}STDMETHODIMP CMatchFinderMT::GetMatches(UInt32 *distances){ if (m_Pos == m_PosLimit) GetNextBlock(); if (m_Result != S_OK) return m_Result; m_NumAvailableBytes--; m_DataCurrentPos++; const UInt32 *buffer = m_Buffer + m_Pos; UInt32 len = *buffer++; *distances++ = len; m_Pos += 1 + len; for (UInt32 i = 0; i != len; i += 2) { distances[i] = buffer[i]; distances[i + 1] = buffer[i + 1]; } return S_OK; }STDMETHODIMP CMatchFinderMT::Skip(UInt32 num){ do { if (m_Pos == m_PosLimit) GetNextBlock(); if (m_Result != S_OK) return m_Result; m_NumAvailableBytes--; m_DataCurrentPos++; UInt32 len = m_Buffer[m_Pos++]; m_Pos += len; } while(--num != 0); return S_OK; }STDMETHODIMP_(Int32) CMatchFinderMT::NeedChangeBufferPos(UInt32 numCheckBytes){ throw 1;}STDMETHODIMP_(void) CMatchFinderMT::ChangeBufferPos(){ throw 1;}DWORD CMatchFinderMT::ThreadFunc(){ while(true) { bool needStartEvent = true; m_MtCanStart.Lock(); HRESULT result = S_OK; UInt32 blockIndex = 0; while (true) { m_CS[blockIndex].Enter(); if (needStartEvent) { m_MtWasStarted.Set(); needStartEvent = false; } else m_CS[(blockIndex == 0) ? kNumMTBlocks - 1 : blockIndex - 1].Leave(); if (m_Exit) return 0; if (m_StopWriting) { m_MtWasStopped.Set(); m_CS[blockIndex].Leave(); break; } if (result == S_OK) { IMatchFinder *mf = m_MatchFinder; if (mf->NeedChangeBufferPos(kBlockSize) != 0) { // m_AskChangeBufferPos.Set(); m_StopReading[blockIndex] = true; m_CS[blockIndex].Leave(); m_CanChangeBufferPos.Lock(); m_CS[blockIndex].Enter(); const Byte *bufferPosBefore = mf->GetPointerToCurrentPos(); mf->ChangeBufferPos(); m_DataCurrentPos += mf->GetPointerToCurrentPos() - bufferPosBefore; m_BufferPosWasChanged.Set(); } else { UInt32 curPos = blockIndex * kBlockSize; UInt32 limit = curPos + kBlockSize - m_MatchMaxLen - m_MatchMaxLen - 1; UInt32 *buffer = m_Buffer; m_Results[blockIndex] = S_OK; curPos++; UInt32 numAvailableBytes = mf->GetNumAvailableBytes(); buffer[curPos++] = numAvailableBytes; while (numAvailableBytes-- != 0 && curPos < limit) { result = mf->GetMatches(buffer + curPos); if (result != S_OK) { m_Results[blockIndex] = result; break; } curPos += buffer[curPos] + 1; } buffer[blockIndex * kBlockSize] = curPos; } } else { UInt32 curPos = blockIndex * kBlockSize; m_Buffer[curPos] = curPos + 2; // size of buffer m_Buffer[curPos + 1] = 0; // NumAvailableBytes m_Results[blockIndex] = result; // error } if (++blockIndex == kNumMTBlocks) blockIndex = 0; } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -