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