Mercurial > vba-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // MemBlocks.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/MyCom.h" | |
6 | |
7 #include "StreamUtils.h" | |
8 #include "MemBlocks.h" | |
9 | |
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 } | |
28 | |
29 void CMemBlockManager::FreeSpace() | |
30 { | |
31 ::MidFree(_data); | |
32 _data = 0; | |
33 _headFree= 0; | |
34 } | |
35 | |
36 void *CMemBlockManager::AllocateBlock() | |
37 { | |
38 if (_headFree == 0) | |
39 return 0; | |
40 void *p = _headFree; | |
41 _headFree = *(void **)_headFree; | |
42 return p; | |
43 } | |
44 | |
45 void CMemBlockManager::FreeBlock(void *p) | |
46 { | |
47 if (p == 0) | |
48 return; | |
49 *(void **)p = _headFree; | |
50 _headFree = p; | |
51 } | |
52 | |
53 | |
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 } | |
64 | |
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 } | |
78 | |
79 void CMemBlockManagerMt::FreeSpace() | |
80 { | |
81 Semaphore.Close(); | |
82 CMemBlockManager::FreeSpace(); | |
83 } | |
84 | |
85 void *CMemBlockManagerMt::AllocateBlock() | |
86 { | |
87 // Semaphore.Lock(); | |
88 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); | |
89 return CMemBlockManager::AllocateBlock(); | |
90 } | |
91 | |
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 } | |
103 | |
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 } | |
113 | |
114 void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager) | |
115 { | |
116 Free(manager); | |
117 Blocks.ClearAndFree(); | |
118 } | |
119 | |
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 } | |
135 | |
136 | |
137 void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager) | |
138 { | |
139 memManager->FreeBlock(Blocks[index], LockMode); | |
140 Blocks[index] = 0; | |
141 } | |
142 | |
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 } | |
152 | |
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 } | |
165 | |
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 } |