Mercurial > vba-linux
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 +}