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.cpp
3 #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) const
121 {
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 else
177 FreeBlock(i, memManager);
178 Blocks[i] = 0;
179 totalSize += blockSize;
180 }
181 blocks.TotalSize = TotalSize;
182 Free(memManager);
183 }