diff src/win32/7zip/7z/CPP/7zip/Common/MemBlocks.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Common/MemBlocks.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,183 @@
     1.4 +// MemBlocks.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +#include "Common/MyCom.h"
     1.9 +
    1.10 +#include "StreamUtils.h"
    1.11 +#include "MemBlocks.h"
    1.12 +
    1.13 +bool CMemBlockManager::AllocateSpace(size_t numBlocks)
    1.14 +{
    1.15 +  FreeSpace();
    1.16 +  if (_blockSize < sizeof(void *) || numBlocks < 1)
    1.17 +    return false;
    1.18 +  size_t totalSize = numBlocks * _blockSize;
    1.19 +  if (totalSize / _blockSize != numBlocks)
    1.20 +    return false;
    1.21 +  _data = ::MidAlloc(totalSize);
    1.22 +  if (_data == 0)
    1.23 +    return false;
    1.24 +  Byte *p = (Byte *)_data;
    1.25 +  for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
    1.26 +    *(Byte **)p = (p + _blockSize);
    1.27 +  *(Byte **)p = 0;
    1.28 +  _headFree = _data;
    1.29 +  return true;
    1.30 +}
    1.31 +
    1.32 +void CMemBlockManager::FreeSpace()
    1.33 +{
    1.34 +  ::MidFree(_data);
    1.35 +  _data = 0;
    1.36 +  _headFree= 0;
    1.37 +}
    1.38 +
    1.39 +void *CMemBlockManager::AllocateBlock()
    1.40 +{
    1.41 +  if (_headFree == 0)
    1.42 +    return 0;
    1.43 +  void *p = _headFree;
    1.44 +  _headFree = *(void **)_headFree;
    1.45 +  return p;
    1.46 +}
    1.47 +
    1.48 +void CMemBlockManager::FreeBlock(void *p)
    1.49 +{
    1.50 +  if (p == 0)
    1.51 +    return;
    1.52 +  *(void **)p = _headFree;
    1.53 +  _headFree = p;
    1.54 +}
    1.55 +
    1.56 +
    1.57 +HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
    1.58 +{
    1.59 +  if (numNoLockBlocks > numBlocks)
    1.60 +    return E_INVALIDARG;
    1.61 +  if (!CMemBlockManager::AllocateSpace(numBlocks))
    1.62 +    return E_OUTOFMEMORY;
    1.63 +  size_t numLockBlocks = numBlocks - numNoLockBlocks;
    1.64 +  Semaphore.Close();
    1.65 +  return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);
    1.66 +}
    1.67 +
    1.68 +HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
    1.69 +{
    1.70 +  if (numNoLockBlocks > desiredNumberOfBlocks)
    1.71 +    return E_INVALIDARG;
    1.72 +  for (;;)
    1.73 +  {
    1.74 +    if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0)
    1.75 +      return 0;
    1.76 +    if (desiredNumberOfBlocks == numNoLockBlocks)
    1.77 +      return E_OUTOFMEMORY;
    1.78 +    desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
    1.79 +  }
    1.80 +}
    1.81 +
    1.82 +void CMemBlockManagerMt::FreeSpace()
    1.83 +{
    1.84 +  Semaphore.Close();
    1.85 +  CMemBlockManager::FreeSpace();
    1.86 +}
    1.87 +
    1.88 +void *CMemBlockManagerMt::AllocateBlock()
    1.89 +{
    1.90 +  // Semaphore.Lock();
    1.91 +  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
    1.92 +  return CMemBlockManager::AllocateBlock();
    1.93 +}
    1.94 +
    1.95 +void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
    1.96 +{
    1.97 +  if (p == 0)
    1.98 +    return;
    1.99 +  {
   1.100 +    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
   1.101 +    CMemBlockManager::FreeBlock(p);
   1.102 +  }
   1.103 +  if (lockMode)
   1.104 +    Semaphore.Release();
   1.105 +}
   1.106 +
   1.107 +void CMemBlocks::Free(CMemBlockManagerMt *manager)
   1.108 +{
   1.109 +  while(Blocks.Size() > 0)
   1.110 +  {
   1.111 +    manager->FreeBlock(Blocks.Back());
   1.112 +    Blocks.DeleteBack();
   1.113 +  }
   1.114 +  TotalSize = 0;
   1.115 +}
   1.116 +
   1.117 +void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
   1.118 +{
   1.119 +  Free(manager);
   1.120 +  Blocks.ClearAndFree();
   1.121 +}
   1.122 +
   1.123 +HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
   1.124 +{
   1.125 +  UInt64 totalSize = TotalSize;
   1.126 +  for (int blockIndex = 0; totalSize > 0; blockIndex++)
   1.127 +  {
   1.128 +    UInt32 curSize = (UInt32)blockSize;
   1.129 +    if (totalSize < curSize)
   1.130 +      curSize = (UInt32)totalSize;
   1.131 +    if (blockIndex >= Blocks.Size())
   1.132 +      return E_FAIL;
   1.133 +    RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));
   1.134 +    totalSize -= curSize;
   1.135 +  }
   1.136 +  return S_OK;
   1.137 +}
   1.138 +
   1.139 +
   1.140 +void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)
   1.141 +{
   1.142 +  memManager->FreeBlock(Blocks[index], LockMode);
   1.143 +  Blocks[index] = 0;
   1.144 +}
   1.145 +
   1.146 +void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
   1.147 +{
   1.148 +  while (Blocks.Size() > 0)
   1.149 +  {
   1.150 +    FreeBlock(Blocks.Size() - 1, memManager);
   1.151 +    Blocks.DeleteBack();
   1.152 +  }
   1.153 +  TotalSize = 0;
   1.154 +}
   1.155 +
   1.156 +HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
   1.157 +{
   1.158 +  if (LockMode)
   1.159 +  {
   1.160 +    if (Blocks.Size() > 0)
   1.161 +    {
   1.162 +      RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));
   1.163 +    }
   1.164 +    LockMode = false;
   1.165 +  }
   1.166 +  return 0;
   1.167 +}
   1.168 +
   1.169 +void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
   1.170 +{
   1.171 +  blocks.Free(memManager);
   1.172 +  blocks.LockMode = LockMode;
   1.173 +  UInt64 totalSize = 0;
   1.174 +  size_t blockSize = memManager->GetBlockSize();
   1.175 +  for (int i = 0; i < Blocks.Size(); i++)
   1.176 +  {
   1.177 +    if (totalSize < TotalSize)
   1.178 +      blocks.Blocks.Add(Blocks[i]);
   1.179 +    else
   1.180 +      FreeBlock(i, memManager);
   1.181 +    Blocks[i] = 0;
   1.182 +    totalSize += blockSize;
   1.183 +  }
   1.184 +  blocks.TotalSize = TotalSize;
   1.185 +  Free(memManager);
   1.186 +}