Mercurial > vba-linux
view 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 source
1 // MemBlocks.cpp3 #include "StdAfx.h"5 #include "Common/MyCom.h"7 #include "StreamUtils.h"8 #include "MemBlocks.h"10 bool CMemBlockManager::AllocateSpace(size_t numBlocks)11 {12 FreeSpace();13 if (_blockSize < sizeof(void *) || numBlocks < 1)14 return false;15 size_t totalSize = numBlocks * _blockSize;16 if (totalSize / _blockSize != numBlocks)17 return false;18 _data = ::MidAlloc(totalSize);19 if (_data == 0)20 return false;21 Byte *p = (Byte *)_data;22 for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)23 *(Byte **)p = (p + _blockSize);24 *(Byte **)p = 0;25 _headFree = _data;26 return true;27 }29 void CMemBlockManager::FreeSpace()30 {31 ::MidFree(_data);32 _data = 0;33 _headFree= 0;34 }36 void *CMemBlockManager::AllocateBlock()37 {38 if (_headFree == 0)39 return 0;40 void *p = _headFree;41 _headFree = *(void **)_headFree;42 return p;43 }45 void CMemBlockManager::FreeBlock(void *p)46 {47 if (p == 0)48 return;49 *(void **)p = _headFree;50 _headFree = p;51 }54 HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)55 {56 if (numNoLockBlocks > numBlocks)57 return E_INVALIDARG;58 if (!CMemBlockManager::AllocateSpace(numBlocks))59 return E_OUTOFMEMORY;60 size_t numLockBlocks = numBlocks - numNoLockBlocks;61 Semaphore.Close();62 return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);63 }65 HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)66 {67 if (numNoLockBlocks > desiredNumberOfBlocks)68 return E_INVALIDARG;69 for (;;)70 {71 if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0)72 return 0;73 if (desiredNumberOfBlocks == numNoLockBlocks)74 return E_OUTOFMEMORY;75 desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);76 }77 }79 void CMemBlockManagerMt::FreeSpace()80 {81 Semaphore.Close();82 CMemBlockManager::FreeSpace();83 }85 void *CMemBlockManagerMt::AllocateBlock()86 {87 // Semaphore.Lock();88 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);89 return CMemBlockManager::AllocateBlock();90 }92 void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)93 {94 if (p == 0)95 return;96 {97 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);98 CMemBlockManager::FreeBlock(p);99 }100 if (lockMode)101 Semaphore.Release();102 }104 void CMemBlocks::Free(CMemBlockManagerMt *manager)105 {106 while(Blocks.Size() > 0)107 {108 manager->FreeBlock(Blocks.Back());109 Blocks.DeleteBack();110 }111 TotalSize = 0;112 }114 void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)115 {116 Free(manager);117 Blocks.ClearAndFree();118 }120 HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const121 {122 UInt64 totalSize = TotalSize;123 for (int blockIndex = 0; totalSize > 0; blockIndex++)124 {125 UInt32 curSize = (UInt32)blockSize;126 if (totalSize < curSize)127 curSize = (UInt32)totalSize;128 if (blockIndex >= Blocks.Size())129 return E_FAIL;130 RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));131 totalSize -= curSize;132 }133 return S_OK;134 }137 void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)138 {139 memManager->FreeBlock(Blocks[index], LockMode);140 Blocks[index] = 0;141 }143 void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)144 {145 while (Blocks.Size() > 0)146 {147 FreeBlock(Blocks.Size() - 1, memManager);148 Blocks.DeleteBack();149 }150 TotalSize = 0;151 }153 HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)154 {155 if (LockMode)156 {157 if (Blocks.Size() > 0)158 {159 RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));160 }161 LockMode = false;162 }163 return 0;164 }166 void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)167 {168 blocks.Free(memManager);169 blocks.LockMode = LockMode;170 UInt64 totalSize = 0;171 size_t blockSize = memManager->GetBlockSize();172 for (int i = 0; i < Blocks.Size(); i++)173 {174 if (totalSize < TotalSize)175 blocks.Blocks.Add(Blocks[i]);176 else177 FreeBlock(i, memManager);178 Blocks[i] = 0;179 totalSize += blockSize;180 }181 blocks.TotalSize = TotalSize;182 Free(memManager);183 }