1 // MemBlocks.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/Alloc.h"
6
7 #include "MemBlocks.h"
8 #include "StreamUtils.h"
9
AllocateSpace_bool(size_t numBlocks)10 bool CMemBlockManager::AllocateSpace_bool(size_t numBlocks)
11 {
12 FreeSpace();
13 if (numBlocks == 0)
14 {
15 return true;
16 // return false;
17 }
18 if (_blockSize < sizeof(void *))
19 return false;
20 const size_t totalSize = numBlocks * _blockSize;
21 if (totalSize / _blockSize != numBlocks)
22 return false;
23 _data = ::MidAlloc(totalSize);
24 if (!_data)
25 return false;
26 Byte *p = (Byte *)_data;
27 for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
28 *(Byte **)(void *)p = (p + _blockSize);
29 *(Byte **)(void *)p = NULL;
30 _headFree = _data;
31 return true;
32 }
33
FreeSpace()34 void CMemBlockManager::FreeSpace()
35 {
36 ::MidFree(_data);
37 _data = 0;
38 _headFree= 0;
39 }
40
AllocateBlock()41 void *CMemBlockManager::AllocateBlock()
42 {
43 void *p = _headFree;
44 if (p)
45 _headFree = *(void **)p;
46 return p;
47 }
48
FreeBlock(void * p)49 void CMemBlockManager::FreeBlock(void *p)
50 {
51 if (!p)
52 return;
53 *(void **)p = _headFree;
54 _headFree = p;
55 }
56
57
58 // #include <stdio.h>
59
AllocateSpace(size_t numBlocks,size_t numNoLockBlocks)60 HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
61 {
62 if (numNoLockBlocks > numBlocks)
63 return E_INVALIDARG;
64 const size_t numLockBlocks = numBlocks - numNoLockBlocks;
65 UInt32 maxCount = (UInt32)numLockBlocks;
66 if (maxCount != numLockBlocks)
67 return E_OUTOFMEMORY;
68 if (!CMemBlockManager::AllocateSpace_bool(numBlocks))
69 return E_OUTOFMEMORY;
70 // we need (maxCount = 1), if we want to create non-use empty Semaphore
71 if (maxCount == 0)
72 maxCount = 1;
73
74 // printf("\n Synchro.Create() \n");
75 WRes wres;
76 #ifndef _WIN32
77 Semaphore.Close();
78 wres = Synchro.Create();
79 if (wres != 0)
80 return HRESULT_FROM_WIN32(wres);
81 wres = Semaphore.Create(&Synchro, (UInt32)numLockBlocks, maxCount);
82 #else
83 wres = Semaphore.OptCreateInit((UInt32)numLockBlocks, maxCount);
84 #endif
85
86 return HRESULT_FROM_WIN32(wres);
87 }
88
89
AllocateSpaceAlways(size_t desiredNumberOfBlocks,size_t numNoLockBlocks)90 HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
91 {
92 // desiredNumberOfBlocks = 0; // for debug
93 if (numNoLockBlocks > desiredNumberOfBlocks)
94 return E_INVALIDARG;
95 for (;;)
96 {
97 // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY;
98 HRes hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks);
99 if (hres != E_OUTOFMEMORY)
100 return hres;
101 if (desiredNumberOfBlocks == numNoLockBlocks)
102 return E_OUTOFMEMORY;
103 desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
104 }
105 }
106
FreeSpace()107 void CMemBlockManagerMt::FreeSpace()
108 {
109 Semaphore.Close();
110 CMemBlockManager::FreeSpace();
111 }
112
AllocateBlock()113 void *CMemBlockManagerMt::AllocateBlock()
114 {
115 // Semaphore.Lock();
116 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
117 return CMemBlockManager::AllocateBlock();
118 }
119
FreeBlock(void * p,bool lockMode)120 void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
121 {
122 if (!p)
123 return;
124 {
125 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
126 CMemBlockManager::FreeBlock(p);
127 }
128 if (lockMode)
129 Semaphore.Release();
130 }
131
132
133
Free(CMemBlockManagerMt * manager)134 void CMemBlocks::Free(CMemBlockManagerMt *manager)
135 {
136 while (Blocks.Size() > 0)
137 {
138 manager->FreeBlock(Blocks.Back());
139 Blocks.DeleteBack();
140 }
141 TotalSize = 0;
142 }
143
FreeOpt(CMemBlockManagerMt * manager)144 void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
145 {
146 Free(manager);
147 Blocks.ClearAndFree();
148 }
149
WriteToStream(size_t blockSize,ISequentialOutStream * outStream) const150 HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
151 {
152 UInt64 totalSize = TotalSize;
153 for (unsigned blockIndex = 0; totalSize > 0; blockIndex++)
154 {
155 size_t curSize = blockSize;
156 if (curSize > totalSize)
157 curSize = (size_t)totalSize;
158 if (blockIndex >= Blocks.Size())
159 return E_FAIL;
160 RINOK(WriteStream(outStream, Blocks[blockIndex], curSize));
161 totalSize -= curSize;
162 }
163 return S_OK;
164 }
165
166
FreeBlock(unsigned index,CMemBlockManagerMt * memManager)167 void CMemLockBlocks::FreeBlock(unsigned index, CMemBlockManagerMt *memManager)
168 {
169 memManager->FreeBlock(Blocks[index], LockMode);
170 Blocks[index] = NULL;
171 }
172
Free(CMemBlockManagerMt * memManager)173 void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
174 {
175 while (Blocks.Size() > 0)
176 {
177 FreeBlock(Blocks.Size() - 1, memManager);
178 Blocks.DeleteBack();
179 }
180 TotalSize = 0;
181 }
182
183 /*
184 HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
185 {
186 if (LockMode)
187 {
188 if (Blocks.Size() > 0)
189 {
190 RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));
191 }
192 LockMode = false;
193 }
194 return 0;
195 }
196 */
197
Detach(CMemLockBlocks & blocks,CMemBlockManagerMt * memManager)198 void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
199 {
200 blocks.Free(memManager);
201 blocks.LockMode = LockMode;
202 UInt64 totalSize = 0;
203 const size_t blockSize = memManager->GetBlockSize();
204 FOR_VECTOR (i, Blocks)
205 {
206 if (totalSize < TotalSize)
207 blocks.Blocks.Add(Blocks[i]);
208 else
209 FreeBlock(i, memManager);
210 Blocks[i] = 0;
211 totalSize += blockSize;
212 }
213 blocks.TotalSize = TotalSize;
214 Free(memManager);
215 }
216