This commit is contained in:
Igor Pavlov
2003-12-11 00:00:00 +00:00
committed by Kornel Lesiński
commit 8c1b5c7b7e
982 changed files with 118799 additions and 0 deletions

317
7zip/Compress/LZ/MT/MT.cpp Executable file
View File

@@ -0,0 +1,317 @@
// MT_MF.cpp
#include "StdAfx.h"
#include "MT.h"
class CMatchFinderCallback:
public IMatchFinderCallback,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
STDMETHOD(BeforeChangingBufferPos)();
STDMETHOD(AfterChangingBufferPos)();
public:
CMatchFinderMT *m_MatchFinderMT;
const BYTE *m_BufferPosBefore;
};
STDMETHODIMP CMatchFinderCallback::BeforeChangingBufferPos()
{
m_MatchFinderMT->m_AskChangeBufferPos.Set();
m_MatchFinderMT->m_CanChangeBufferPos.Lock();
m_BufferPosBefore = m_MatchFinderMT->m_MatchFinder->GetPointerToCurrentPos();
return S_OK;
}
STDMETHODIMP CMatchFinderCallback::AfterChangingBufferPos()
{
m_MatchFinderMT->m_DataCurrentPos +=
m_MatchFinderMT->m_MatchFinder->GetPointerToCurrentPos() - m_BufferPosBefore;
m_MatchFinderMT->m_BufferPosWasChanged.Set();
return S_OK;
}
HRESULT CMatchFinderMT::SetMatchFinder(IMatchFinder *aMatchFinder,
UINT32 multiThreadMult)
{
_multiThreadMult = multiThreadMult;
m_MatchFinder = aMatchFinder;
CMyComPtr<IMatchFinderSetCallback> matchFinderSetCallback;
if (m_MatchFinder.QueryInterface(IID_IMatchFinderSetCallback,
&matchFinderSetCallback) == S_OK)
{
CMatchFinderCallback *matchFinderCallbackSpec =
new CMatchFinderCallback;
CMyComPtr<IMatchFinderCallback> matchFinderCallback = matchFinderCallbackSpec;
matchFinderCallbackSpec->m_MatchFinderMT = this;
matchFinderSetCallback->SetCallback(matchFinderCallback);
return S_OK;
}
else
return E_FAIL;
}
STDMETHODIMP CMatchFinderMT::Init(ISequentialInStream *aStream)
{
// OutputDebugString("Init\n");
m_AskChangeBufferPos.Reset();
m_CanChangeBufferPos.Reset();
m_BufferPosWasChanged.Reset();
m_StopWriting.Reset();
m_WritingWasStopped.Reset();
m_NeedStart = true;
HRESULT aResult = m_MatchFinder->Init(aStream);
if (aResult == S_OK)
m_DataCurrentPos = m_MatchFinder->GetPointerToCurrentPos();
return aResult;
}
STDMETHODIMP_(void) CMatchFinderMT::ReleaseStream()
{
// OutputDebugString("ReleaseStream\n");
m_StopWriting.Set();
m_WritingWasStopped.Lock();
// OutputDebugString("m_WritingWasStopped\n");
m_MatchFinder->ReleaseStream();
}
STDMETHODIMP CMatchFinderMT::MovePos()
{
m_NumAvailableBytesCurrent--;
m_DataCurrentPos++;
return S_OK;
}
STDMETHODIMP_(BYTE) CMatchFinderMT::GetIndexByte(UINT32 anIndex)
{
return m_DataCurrentPos[anIndex];
}
STDMETHODIMP_(UINT32) CMatchFinderMT::GetMatchLen(UINT32 aIndex,
UINT32 aBack, UINT32 aLimit)
{
if (int(aIndex + aLimit) > m_NumAvailableBytesCurrent)
aLimit = m_NumAvailableBytesCurrent - (aIndex);
aBack++;
const BYTE *pby = m_DataCurrentPos + aIndex;
UINT32 i;
for(i = 0; i < aLimit && pby[i] == pby[i - aBack]; i++);
/*
char aSz[100];
sprintf(aSz, "GetMatchLen = %d", i);
OutputDebugString(aSz);
OutputDebugString("\n");
*/
return i;
// return m_MatchFinder->GetMatchLen(aIndex, aBack, aLimit); }
}
STDMETHODIMP_(const BYTE *) CMatchFinderMT::GetPointerToCurrentPos()
{
return m_DataCurrentPos;
}
STDMETHODIMP_(UINT32) CMatchFinderMT::GetNumAvailableBytes()
{
if (m_NeedStart)
return m_MatchFinder->GetNumAvailableBytes();
else
return m_NumAvailableBytesCurrent;
}
void CMatchFinderMT::FreeMem()
{
delete []m_Buffer;
}
STDMETHODIMP CMatchFinderMT::Create(UINT32 aSizeHistory,
UINT32 aKeepAddBufferBefore, UINT32 matchMaxLen,
UINT32 aKeepAddBufferAfter)
{
FreeMem();
m_MatchMaxLen = matchMaxLen;
m_BlockSize = (matchMaxLen + 1) * _multiThreadMult;
UINT32 aBufferSize = m_BlockSize * kNumMTBlocks;
m_Buffer = new UINT32[aBufferSize];
for (int i = 0; i < kNumMTBlocks; i++)
m_Buffers[i] = &m_Buffer[i * m_BlockSize];
m_NeedStart = true;
aKeepAddBufferBefore += aBufferSize;
return m_MatchFinder->Create(aSizeHistory,
aKeepAddBufferBefore, matchMaxLen,
aKeepAddBufferAfter);
}
static DWORD WINAPI MFThread(void *aThreadCoderInfo)
{
CMatchFinderMT &aMT = *(CMatchFinderMT *)aThreadCoderInfo;
while (true)
{
HANDLE anEvents[3] = { aMT.m_ExitEvent, aMT.m_StopWriting, aMT.m_CanWriteEvents[aMT.m_WriteBufferIndex] } ;
DWORD anWaitResult = ::WaitForMultipleObjects(3, anEvents, FALSE, INFINITE);
if (anWaitResult == WAIT_OBJECT_0 + 0)
return 0;
if (anWaitResult == WAIT_OBJECT_0 + 1)
{
// OutputDebugString("m_StopWriting\n");
aMT.m_WriteBufferIndex = 0;
for (int i = 0; i < kNumMTBlocks; i++)
aMT.m_CanWriteEvents[i].Reset();
aMT.m_WritingWasStopped.Set();
continue;
}
// OutputDebugString("m_CanWriteEvents\n");
UINT32 *aBuffer = aMT.m_Buffers[aMT.m_WriteBufferIndex];
UINT32 aCurPos = 0;
UINT32 aNumBytes = 0;
while (aCurPos + aMT.m_MatchMaxLen + 1 <= aMT.m_BlockSize)
{
if (aMT.m_MatchFinder->GetNumAvailableBytes() == 0)
break;
UINT32 aLen = aMT.m_MatchFinder->GetLongestMatch(aBuffer + aCurPos);
/*
if (aLen == 1)
aLen = 0;
*/
aBuffer[aCurPos] = aLen;
aCurPos += aLen + 1;
HRESULT aResult = aMT.m_MatchFinder->MovePos();
if (aResult != S_OK)
throw 124459;
aNumBytes++;
}
aMT.m_LimitPos[aMT.m_WriteBufferIndex] = aCurPos;
aMT.m_NumAvailableBytes[aMT.m_WriteBufferIndex] =
aNumBytes + aMT.m_MatchFinder->GetNumAvailableBytes();
// char aSz[100];
// sprintf(aSz, "x = %d", aMT.m_WriteBufferIndex);
// OutputDebugString(aSz);
// OutputDebugString("aMT.m_CanReadEvents\n");
aMT.m_CanReadEvents[aMT.m_WriteBufferIndex].Set();
aMT.m_WriteBufferIndex++;
if (aMT.m_WriteBufferIndex == kNumMTBlocks)
aMT.m_WriteBufferIndex = 0;
}
/*
while(true)
{
if (!((CCoderMixer2 *)aThreadCoderInfo)->MyCode())
return 0;
}
*/
}
CMatchFinderMT::CMatchFinderMT():
m_Buffer(0),
_multiThreadMult(100)
{
for (int i = 0; i < kNumMTBlocks; i++)
{
m_CanReadEvents[i].Reset();
m_CanWriteEvents[i].Reset();
}
m_ReadBufferIndex = 0;
m_WriteBufferIndex = 0;
m_ExitEvent.Reset();
if (!m_Thread.Create(MFThread, this))
throw 271826;
}
CMatchFinderMT::~CMatchFinderMT()
{
m_ExitEvent.Set();
if (HANDLE(m_Thread) != 0)
::WaitForSingleObject(m_Thread, INFINITE);
FreeMem();
}
void CMatchFinderMT::Start()
{
// OutputDebugString("Start\n");
m_AskChangeBufferPos.Reset();
m_CanChangeBufferPos.Reset();
m_BufferPosWasChanged.Reset();
m_WriteBufferIndex = 0;
m_ReadBufferIndex = 0;
m_NeedStart = false;
m_CurrentPos = 0;
m_CurrentLimitPos = 0;
int i;
for (i = 0; i < kNumMTBlocks; i++)
m_CanReadEvents[i].Reset();
for (i = kNumMTBlocks - 1; i >= 0; i--)
m_CanWriteEvents[i].Set();
}
STDMETHODIMP_(UINT32) CMatchFinderMT::GetLongestMatch(UINT32 *aDistances)
{
// OutputDebugString("GetLongestMatch\n");
if (m_NeedStart)
Start();
/*
if (m_CurrentPos > m_CurrentLimitPos)
throw 1123324;
*/
if (m_CurrentPos == m_CurrentLimitPos)
{
// OutputDebugString("m_CurrentPos == m_CurrentLimitPos\n");
while (true)
{
/*
char aSz[100];
sprintf(aSz, "m_CanReadEvents[m_ReadBufferIndex] = %d\n", m_ReadBufferIndex);
OutputDebugString(aSz);
OutputDebugString("\n");
*/
HANDLE anEvents[2] = { m_AskChangeBufferPos, m_CanReadEvents[m_ReadBufferIndex] } ;
DWORD anWaitResult = ::WaitForMultipleObjects(2, anEvents, FALSE, INFINITE);
if (anWaitResult == WAIT_OBJECT_0 + 1)
break;
m_BufferPosWasChanged.Reset();
m_CanChangeBufferPos.Set();
m_BufferPosWasChanged.Lock();
}
m_CurrentLimitPos = m_LimitPos[m_ReadBufferIndex];
m_NumAvailableBytesCurrent = m_NumAvailableBytes[m_ReadBufferIndex];
m_CurrentPos = 0;
}
if (m_CurrentPos >= m_CurrentLimitPos)
throw 1123324;
const UINT32 *aBuffer = m_Buffers[m_ReadBufferIndex];
UINT32 aLen = aBuffer[m_CurrentPos++];
for (UINT32 i = 1; i <= aLen; i++)
aDistances[i] = aBuffer[m_CurrentPos++];
if (m_CurrentPos == m_CurrentLimitPos)
{
m_CanWriteEvents[m_ReadBufferIndex].Set();
m_ReadBufferIndex++;
if (m_ReadBufferIndex == kNumMTBlocks)
m_ReadBufferIndex = 0;
}
// char aSz[100];
// sprintf(aSz, "m_NumAvailableBytesCurrent = %d", m_NumAvailableBytesCurrent);
// OutputDebugString(aSz);
// OutputDebugString("\n");
return aLen;
}
STDMETHODIMP_(void) CMatchFinderMT::DummyLongestMatch()
{
UINT32 aBuffer[512];
GetLongestMatch(aBuffer);
// m_MatchFinder->DummyLongestMatch();
}

85
7zip/Compress/LZ/MT/MT.h Executable file
View File

@@ -0,0 +1,85 @@
// MT_MF.h
#pragma once
#ifndef __MT_MF_H
#define __MT_MF_H
#include "Common/MyCom.h"
#include "Windows/Thread.h"
#include "Windows/Synchronization.h"
#include "../../../ICoder.h"
#include "../IMatchFinder.h"
const int kNumMTBlocks = 3;
class CMatchFinderMT:
public IMatchFinder,
public CMyUnknownImp
{
MY_UNKNOWN_IMP
STDMETHOD(Init)(ISequentialInStream *aStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(MovePos)();
STDMETHOD_(BYTE, GetIndexByte)(UINT32 anIndex);
STDMETHOD_(UINT32, GetMatchLen)(UINT32 aIndex, UINT32 aBack, UINT32 aLimit);
STDMETHOD_(UINT32, GetNumAvailableBytes)();
STDMETHOD_(const BYTE *, GetPointerToCurrentPos)();
STDMETHOD(Create)(UINT32 aSizeHistory,
UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen,
UINT32 aKeepAddBufferAfter);
STDMETHOD_(UINT32, GetLongestMatch)(UINT32 *aDistances);
STDMETHOD_(void, DummyLongestMatch)();
private:
public:
CMyComPtr<IMatchFinder> m_MatchFinder;
UINT32 m_MatchMaxLen;
UINT32 m_BlockSize;
// UINT32 m_BufferSize;
UINT32 *m_Buffer;
UINT32 *m_Buffers[kNumMTBlocks];
bool m_NeedStart;
UINT32 m_WriteBufferIndex;
UINT32 m_ReadBufferIndex;
NWindows::NSynchronization::CAutoResetEvent m_StopWriting;
NWindows::NSynchronization::CAutoResetEvent m_WritingWasStopped;
NWindows::NSynchronization::CAutoResetEvent m_AskChangeBufferPos;
NWindows::NSynchronization::CAutoResetEvent m_CanChangeBufferPos;
NWindows::NSynchronization::CAutoResetEvent m_BufferPosWasChanged;
NWindows::NSynchronization::CManualResetEvent m_ExitEvent;
// NWindows::NSynchronization::CManualResetEvent m_NewStart;
NWindows::NSynchronization::CAutoResetEvent m_CanReadEvents[kNumMTBlocks];
NWindows::NSynchronization::CAutoResetEvent m_CanWriteEvents[kNumMTBlocks];
UINT32 m_LimitPos[kNumMTBlocks];
UINT32 m_NumAvailableBytes[kNumMTBlocks];
UINT32 m_NumAvailableBytesCurrent;
const BYTE *m_DataCurrentPos;
UINT32 m_CurrentLimitPos;
UINT32 m_CurrentPos;
NWindows::CThread m_Thread;
// bool m_WriteWasClosed;
UINT32 _multiThreadMult;
public:
CMatchFinderMT();
~CMatchFinderMT();
void Start();
void FreeMem();
HRESULT SetMatchFinder(IMatchFinder *aMatchFinder,
UINT32 multiThreadMult = 200);
};
#endif

8
7zip/Compress/LZ/MT/StdAfx.h Executable file
View File

@@ -0,0 +1,8 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#endif