jbuff.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <assert.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #ifndef WIN32
  23. #include <sys/mman.h>
  24. #define LARGEMEM_USE_MMAP_SIZE 0x10000 // in largemem use mmap for chunks bigger than 64K
  25. #endif
  26. #include "jbuff.hpp"
  27. #include "jexcept.hpp"
  28. #include "jmisc.hpp"
  29. #include "jutil.hpp"
  30. #include "jvmem.hpp"
  31. #ifdef _DEBUG
  32. #define KILL_CLEARS_MEMORY
  33. //#define TRACE_LARGEMEM
  34. //#define TRACE_LARGEMEM_ALLOC
  35. #define TRACE_LARGEMEM_OOM
  36. #endif
  37. #if 1
  38. #define ChunkSize 0x10000
  39. #define DOUBLE_LIMIT 0x7fffffff // avoid doubling hitting 0 and infinite loop
  40. #else
  41. #define ChunkSize 2048
  42. #define DOUBLE_LIMIT 4096
  43. #endif
  44. #define FIRST_CHUNK_SIZE 8
  45. #define DETACH_GRANULARITY 16
  46. #ifdef _DEBUG
  47. #define CHECKREADPOS(len) assertex(readPos+(len)<=length())
  48. #else
  49. #define CHECKREADPOS(len)
  50. #endif
  51. //-----------------------------------------------------------------------
  52. jlib_decl void *checked_realloc(void *orig, size32_t newlen, size32_t origlen,int errcode)
  53. {
  54. if (newlen==0) {
  55. free(orig);
  56. return NULL;
  57. }
  58. if (orig==NULL)
  59. return checked_malloc(newlen,errcode);
  60. void *ret = realloc(orig, newlen);
  61. if (!ret)
  62. RaiseOutOfMemException(errcode, newlen, origlen);
  63. return ret;
  64. }
  65. class jlib_thrown_decl COutOfMemException: public CInterface, implements IOutOfMemException
  66. {
  67. int errcode;
  68. size32_t wanted;
  69. size32_t got;
  70. static int recursion;
  71. bool expected;
  72. public:
  73. IMPLEMENT_IINTERFACE;
  74. COutOfMemException(int _errcode,size32_t _wanted,memsize_t _got,bool _expected)
  75. {
  76. errcode = _errcode;
  77. wanted = _wanted;
  78. expected = _expected;
  79. got = _got;
  80. // DebugBreak();
  81. if ((recursion++==0)&&!expected) {
  82. // Bit risky if *very* out of memory so protect against recursion and catch exceptions
  83. try {
  84. // try to log
  85. PROGLOG("Jbuff: Out of Memory (%d,%d,%"I64F"dk)",_errcode,_wanted,(unsigned __int64) (got/1024));
  86. PrintStackReport();
  87. PrintMemoryReport();
  88. }
  89. catch (...) {
  90. }
  91. }
  92. recursion--;
  93. };
  94. int errorCode() const { return errcode; }
  95. StringBuffer & errorMessage(StringBuffer &str) const
  96. {
  97. str.append("Jbuff: Out of Memory (").append(wanted);
  98. if (got)
  99. str.append(',').append(got/1024);
  100. return str.append("k)");
  101. }
  102. MessageAudience errorAudience() const { return MSGAUD_user; }
  103. };
  104. int COutOfMemException::recursion=0;
  105. IOutOfMemException *createOutOfMemException(int errcode,size32_t wanted,memsize_t got,bool expected)
  106. {
  107. return new COutOfMemException(errcode,wanted,got,expected);
  108. }
  109. void RaiseOutOfMemException(int errcode, size32_t wanted, size32_t got,bool expected)
  110. {
  111. throw createOutOfMemException(errcode, wanted, got,expected);
  112. }
  113. MemoryAttr::MemoryAttr(size32_t _len)
  114. {
  115. ptr = checked_malloc(_len,-1);
  116. len = _len;
  117. }
  118. MemoryAttr::MemoryAttr(size32_t _len, const void * _ptr)
  119. {
  120. len = 0;
  121. ptr = NULL;
  122. set(_len, _ptr);
  123. }
  124. MemoryAttr::MemoryAttr(const MemoryAttr & src)
  125. {
  126. len = 0;
  127. ptr = NULL;
  128. set(src.length(), src.get());
  129. }
  130. void MemoryAttr::set(size32_t _len, const void * _ptr)
  131. {
  132. memcpy(allocate(_len), _ptr, _len);
  133. }
  134. void MemoryAttr::setOwn(size32_t _len, void * _ptr)
  135. {
  136. free(ptr);
  137. len = _len;
  138. ptr = _ptr;
  139. }
  140. void MemoryAttr::clear()
  141. {
  142. free(ptr);
  143. ptr = NULL;
  144. len = 0;
  145. }
  146. void * MemoryAttr::detach()
  147. {
  148. void * ret=ptr;
  149. ptr = NULL;
  150. len = 0;
  151. return ret;
  152. }
  153. int MemoryAttr::compare(const MemoryAttr & m1, const MemoryAttr & m2)
  154. {
  155. size32_t len1 = m1.length();
  156. size32_t len2 = m2.length();
  157. size32_t len = len1;
  158. if (len1 > len2)
  159. len = len2;
  160. int compare = memcmp(m1.get(), m2.get(), len);
  161. if (compare == 0)
  162. compare = (len1 > len2) ? +1 : (len1 < len2) ? -1 : 0;
  163. return compare;
  164. }
  165. void * MemoryAttr::allocate(size32_t _len)
  166. {
  167. if (_len==len)
  168. return ptr;
  169. clear();
  170. ptr = checked_malloc(_len,-2);
  171. len = _len;
  172. return ptr;
  173. }
  174. void * MemoryAttr::ensure(size32_t _len)
  175. {
  176. if (_len <=len)
  177. return ptr;
  178. return reallocate(_len);
  179. }
  180. void * MemoryAttr::reallocate(size32_t _len)
  181. {
  182. if (_len==len)
  183. return ptr;
  184. ptr = checked_realloc(ptr, _len, len, -9);
  185. len = _len;
  186. return ptr;
  187. }
  188. //===========================================================================
  189. void MemoryBuffer::_realloc(size32_t newLen)
  190. {
  191. if (newLen > maxLen)
  192. {
  193. assertex(ownBuffer);
  194. size32_t newMax = maxLen;
  195. //double up to a certain size, otherwise go up in chunks.
  196. if (newLen < DOUBLE_LIMIT)
  197. {
  198. if (newMax == 0)
  199. newMax = FIRST_CHUNK_SIZE;
  200. while (newLen > newMax)
  201. {
  202. newMax += newMax;
  203. }
  204. }
  205. else
  206. /*** ((Size + 1) + (ChunkSize - 1)) & ~(ChunkSize-1) ***/
  207. newMax = (newLen + ChunkSize) & ~(ChunkSize-1);
  208. buffer =(char *)checked_realloc(buffer, newMax, maxLen, -7);
  209. maxLen = newMax;
  210. }
  211. }
  212. void MemoryBuffer::_reallocExact(size32_t newLen)
  213. {
  214. if (newLen > maxLen)
  215. {
  216. assertex(ownBuffer);
  217. buffer =(char *)checked_realloc(buffer, newLen, maxLen, -8);
  218. maxLen = newLen;
  219. }
  220. }
  221. void MemoryBuffer::init()
  222. {
  223. buffer = NULL;
  224. curLen = 0;
  225. maxLen = 0;
  226. ownBuffer = true;
  227. readPos = 0;
  228. swapEndian = false;
  229. }
  230. void *MemoryBuffer::insertDirect(unsigned offset, size32_t insertLen)
  231. {
  232. assertex(offset<=curLen);
  233. unsigned newLen = insertLen + curLen;
  234. _realloc(newLen);
  235. memmove(buffer + offset + insertLen, buffer + offset, curLen - offset);
  236. curLen += insertLen;
  237. return buffer+offset;
  238. }
  239. void MemoryBuffer::ensureCapacity(unsigned max)
  240. {
  241. if (maxLen - curLen < max)
  242. _realloc(curLen + max);
  243. }
  244. void MemoryBuffer::kill()
  245. {
  246. if (ownBuffer)
  247. free(buffer);
  248. }
  249. MemoryBuffer & MemoryBuffer::_remove(unsigned start, unsigned len)
  250. {
  251. if (start > curLen) start = curLen;
  252. if (start + len > curLen) len = curLen - start;
  253. unsigned start2 = start + len;
  254. memmove(buffer + start, buffer + start2, curLen - start2);
  255. setLength(curLen - len);
  256. return *this;
  257. }
  258. void * MemoryBuffer::reserve(unsigned size)
  259. {
  260. _realloc(curLen + size);
  261. void * ret = buffer + curLen;
  262. curLen += size;
  263. return ret;
  264. }
  265. void * MemoryBuffer::reserveTruncate(unsigned size)
  266. {
  267. curLen += size;
  268. _reallocExact(curLen);
  269. truncate();
  270. return buffer + curLen - size;
  271. }
  272. void MemoryBuffer::truncate()
  273. {
  274. if (maxLen>curLen) {
  275. if (curLen==0) {
  276. free(buffer);
  277. buffer = NULL;
  278. }
  279. else
  280. buffer = (char *)realloc(buffer, curLen);
  281. maxLen = curLen;
  282. }
  283. }
  284. void MemoryBuffer::resetBuffer()
  285. {
  286. kill();
  287. init();
  288. }
  289. MemoryBuffer & MemoryBuffer::_reverse()
  290. {
  291. unsigned max = curLen/2;
  292. char * end = buffer + curLen;
  293. unsigned idx;
  294. for (idx = 0; idx < max; idx++)
  295. {
  296. char temp = buffer[idx];
  297. end--;
  298. buffer[idx] = *end;
  299. *end = temp;
  300. }
  301. return *this;
  302. }
  303. void MemoryBuffer::setBuffer(size32_t len, void * _buffer, bool takeOwnership)
  304. {
  305. kill();
  306. buffer = (char *) _buffer;
  307. if (len) assertex(buffer);
  308. curLen = maxLen = len;
  309. ownBuffer = takeOwnership;
  310. readPos = 0;
  311. }
  312. void *MemoryBuffer::detach()
  313. {
  314. void *ret;
  315. if (ownBuffer) {
  316. if (maxLen>curLen+DETACH_GRANULARITY)
  317. buffer = (char *)realloc(buffer,curLen);
  318. ret = buffer;
  319. }
  320. else {
  321. ret = memcpy(checked_malloc(curLen,-3), buffer, curLen);
  322. }
  323. init();
  324. return ret;
  325. }
  326. void *MemoryBuffer::detachOwn()
  327. {
  328. assertex(ownBuffer);
  329. void *ret = buffer;
  330. init();
  331. return ret;
  332. }
  333. void MemoryBuffer::setLength(unsigned len)
  334. {
  335. if (len > curLen)
  336. {
  337. _realloc(len);
  338. memset(buffer + curLen, 0, len-curLen);
  339. }
  340. else
  341. {
  342. #ifdef KILL_CLEARS_MEMORY
  343. if (curLen)
  344. memset(buffer + len, 'x', curLen-len);
  345. #endif
  346. }
  347. curLen = len;
  348. }
  349. void MemoryBuffer::setWritePos(unsigned len)
  350. {
  351. if (len > curLen)
  352. _realloc(len);
  353. curLen = len;
  354. }
  355. #define SWAP(x, y, t) { t t_##x = x; x = y; y = t_##x; }
  356. void MemoryBuffer::swapWith(MemoryBuffer & other)
  357. {
  358. //swap two string buffers. Used for efficiently moving a string on in a pipeline etc.
  359. SWAP(buffer, other.buffer, char *);
  360. SWAP(curLen, other.curLen, size32_t);
  361. SWAP(maxLen, other.maxLen, size32_t);
  362. SWAP(readPos, other.readPos, size32_t);
  363. SWAP(swapEndian, other.swapEndian, bool);
  364. }
  365. //-----------------------------------------------------------------------
  366. MemoryBuffer::MemoryBuffer(size32_t initial)
  367. {
  368. init();
  369. _realloc(initial);
  370. }
  371. MemoryBuffer::MemoryBuffer(MemoryBuffer & value)
  372. {
  373. assertex(!"This should never be used");
  374. }
  375. MemoryBuffer::MemoryBuffer(size32_t len, const void * newBuffer)
  376. {
  377. init();
  378. append(len, newBuffer);
  379. }
  380. MemoryBuffer & MemoryBuffer::append(char value)
  381. {
  382. _realloc(curLen + 1);
  383. buffer[curLen] = value;
  384. ++curLen;
  385. return *this;
  386. }
  387. MemoryBuffer & MemoryBuffer::append(unsigned char value)
  388. {
  389. _realloc(curLen + 1);
  390. buffer[curLen] = value;
  391. ++curLen;
  392. return *this;
  393. }
  394. MemoryBuffer & MemoryBuffer::append(bool value)
  395. {
  396. _realloc(curLen + 1);
  397. buffer[curLen] = (value==0)?0:1;
  398. ++curLen;
  399. return *this;
  400. }
  401. MemoryBuffer & MemoryBuffer::append(const char * value)
  402. {
  403. if (value)
  404. return append((size32_t)strlen(value)+1,value);
  405. else
  406. return append((char)0);
  407. }
  408. MemoryBuffer & MemoryBuffer::append(const unsigned char * value)
  409. {
  410. return append((const char *) value);
  411. }
  412. MemoryBuffer & MemoryBuffer::append(unsigned len, const void * value)
  413. {
  414. _realloc(curLen + len);
  415. memcpy(buffer + curLen, value, len);
  416. curLen += len;
  417. return *this;
  418. }
  419. MemoryBuffer & MemoryBuffer::append(double value)
  420. {
  421. return appendEndian(sizeof(value), &value);
  422. }
  423. MemoryBuffer & MemoryBuffer::append(float value)
  424. {
  425. return appendEndian(sizeof(value), &value);
  426. }
  427. MemoryBuffer & MemoryBuffer::append(short value)
  428. {
  429. return appendEndian(sizeof(value), &value);
  430. }
  431. MemoryBuffer & MemoryBuffer::append(unsigned short value)
  432. {
  433. return appendEndian(sizeof(value), &value);
  434. }
  435. MemoryBuffer & MemoryBuffer::append(int value)
  436. {
  437. return appendEndian(sizeof(value), &value);
  438. }
  439. MemoryBuffer & MemoryBuffer::append(unsigned value)
  440. {
  441. return appendEndian(sizeof(value), &value);
  442. }
  443. #if 0
  444. MemoryBuffer & MemoryBuffer::append(long value)
  445. {
  446. return appendEndian(sizeof(value), &value);
  447. }
  448. MemoryBuffer & MemoryBuffer::append(unsigned long value)
  449. {
  450. return appendEndian(sizeof(value), &value);
  451. }
  452. #endif
  453. MemoryBuffer & MemoryBuffer::append(__int64 value)
  454. {
  455. return appendEndian(sizeof(value), &value);
  456. }
  457. MemoryBuffer & MemoryBuffer::append(unsigned __int64 value)
  458. {
  459. return appendEndian(sizeof(value), &value);
  460. }
  461. MemoryBuffer & MemoryBuffer::append(const MemoryBuffer & value)
  462. {
  463. size32_t SourceLen = value.length();
  464. _realloc(curLen + SourceLen);
  465. memcpy(buffer + curLen, value.toByteArray(), SourceLen);
  466. curLen += SourceLen;
  467. return *this;
  468. }
  469. MemoryBuffer & MemoryBuffer::appendBytes(unsigned char value, unsigned count)
  470. {
  471. _realloc(curLen + count);
  472. memset(buffer+curLen, value, count);
  473. curLen+=count;
  474. return *this;
  475. }
  476. MemoryBuffer & MemoryBuffer::appendEndian(size32_t len, const void * value)
  477. {
  478. _realloc(curLen + len);
  479. if (swapEndian)
  480. _cpyrevn(buffer + curLen, value, len);
  481. else
  482. memcpy(buffer + curLen, value, len);
  483. curLen += len;
  484. return *this;
  485. }
  486. MemoryBuffer & MemoryBuffer::appendSwap(size32_t len, const void * value)
  487. {
  488. _realloc(curLen + len);
  489. _cpyrevn(buffer + curLen, value, len);
  490. curLen += len;
  491. return *this;
  492. }
  493. MemoryBuffer &MemoryBuffer::appendFile(const char *fileName)
  494. {
  495. char buf[1024];
  496. int h = _open(fileName, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
  497. if (h == HFILE_ERROR)
  498. throw MakeStringException(0, "MemoryBuffer: Error reading file : %s", fileName);
  499. append(fileName);
  500. unsigned fileSize = _lseek(h, 0, FILE_END);
  501. _lseek(h, 0, FILE_BEGIN);
  502. append(fileSize);
  503. int r;
  504. while ((r = _read(h, buf, 1024)) != 0)
  505. {
  506. if (-1==r) throw makeErrnoException("MemoryBuffer::appendFile");
  507. append(r, buf);
  508. }
  509. _close(h);
  510. return *this;
  511. }
  512. MemoryBuffer & MemoryBuffer::read(char & value)
  513. {
  514. CHECKREADPOS(sizeof(value));
  515. value = buffer[readPos++];
  516. return *this;
  517. }
  518. MemoryBuffer & MemoryBuffer::read(unsigned char & value)
  519. {
  520. CHECKREADPOS(sizeof(value));
  521. value = buffer[readPos++];
  522. return *this;
  523. }
  524. MemoryBuffer & MemoryBuffer::read(bool & value)
  525. {
  526. CHECKREADPOS(sizeof(value));
  527. char _value = buffer[readPos++];
  528. value = (_value==0 ? false : true);
  529. return *this;
  530. }
  531. MemoryBuffer & MemoryBuffer::read(StringAttr & value)
  532. {
  533. char * src = buffer + readPos;
  534. size32_t len = (size32_t)strlen(src);
  535. CHECKREADPOS(len+1);
  536. value.set(src, len);
  537. readPos += (len+1);
  538. return *this;
  539. }
  540. MemoryBuffer & MemoryBuffer::read(StringBuffer & value)
  541. {
  542. char * src = buffer + readPos;
  543. size32_t len = (size32_t)strlen(src);
  544. CHECKREADPOS(len+1);
  545. value.append(len, src);
  546. readPos += (len+1);
  547. return *this;
  548. }
  549. MemoryBuffer & MemoryBuffer::read(const char * &value)
  550. {
  551. value = buffer+readPos;
  552. size32_t len = (size32_t)strlen(value);
  553. CHECKREADPOS(len+1);
  554. readPos += (len+1);
  555. return *this;
  556. }
  557. MemoryBuffer & MemoryBuffer::read(size32_t len, void * value)
  558. {
  559. CHECKREADPOS(len);
  560. memcpy(value, buffer + readPos, len);
  561. readPos += len;
  562. return *this;
  563. }
  564. MemoryBuffer & MemoryBuffer::read(double & value)
  565. {
  566. return readEndian(sizeof(value), &value);
  567. }
  568. MemoryBuffer & MemoryBuffer::read(float & value)
  569. {
  570. return readEndian(sizeof(value), &value);
  571. }
  572. MemoryBuffer & MemoryBuffer::read(short & value)
  573. {
  574. return readEndian(sizeof(value), &value);
  575. }
  576. MemoryBuffer & MemoryBuffer::read(unsigned short & value)
  577. {
  578. return readEndian(sizeof(value), &value);
  579. }
  580. MemoryBuffer & MemoryBuffer::read(int & value)
  581. {
  582. return readEndian(sizeof(value), &value);
  583. }
  584. MemoryBuffer & MemoryBuffer::read(unsigned & value)
  585. {
  586. return readEndian(sizeof(value), &value);
  587. }
  588. #if 0
  589. MemoryBuffer & MemoryBuffer::read(unsigned long & value)
  590. {
  591. return readEndian(sizeof(value), &value);
  592. }
  593. MemoryBuffer & MemoryBuffer::read(long & value)
  594. {
  595. return readEndian(sizeof(value), &value);
  596. }
  597. #endif
  598. MemoryBuffer & MemoryBuffer::read(unsigned __int64 & value)
  599. {
  600. return readEndian(sizeof(value), &value);
  601. }
  602. MemoryBuffer & MemoryBuffer::read(__int64 & value)
  603. {
  604. return readEndian(sizeof(value), &value);
  605. }
  606. const byte * MemoryBuffer::readDirect(size32_t len)
  607. {
  608. CHECKREADPOS(len);
  609. const byte * ret = (const byte *)buffer + readPos;
  610. readPos += len;
  611. return ret;
  612. }
  613. MemoryBuffer & MemoryBuffer::skip(unsigned len)
  614. {
  615. CHECKREADPOS(len);
  616. readPos += len;
  617. return *this;
  618. }
  619. void MemoryBuffer::writeDirect(size32_t pos,size32_t len,const void *buf)
  620. {
  621. assertex(pos+len<=curLen); // does not extend
  622. memcpy(buffer+pos,buf,len);
  623. }
  624. void MemoryBuffer::writeEndianDirect(size32_t pos,size32_t len,const void *buf)
  625. {
  626. assertex(pos+len<=curLen); // does not extend
  627. if (swapEndian)
  628. _cpyrevn(buffer+pos,buf,len);
  629. else
  630. memcpy(buffer+pos,buf,len);
  631. }
  632. MemoryBuffer & MemoryBuffer::readEndian(size32_t len, void * value)
  633. {
  634. CHECKREADPOS(len);
  635. if (swapEndian)
  636. _cpyrevn(value, buffer + readPos, len);
  637. else
  638. memcpy(value, buffer + readPos, len);
  639. readPos += len;
  640. return *this;
  641. }
  642. MemoryBuffer & MemoryBuffer::readSwap(size32_t len, void * value)
  643. {
  644. CHECKREADPOS(len);
  645. _cpyrevn(value, buffer + readPos, len);
  646. readPos += len;
  647. return *this;
  648. }
  649. MemoryBuffer &MemoryBuffer::readFile(StringAttr &fileName)
  650. {
  651. read(fileName);
  652. unsigned fileSize;
  653. read(fileSize);
  654. int h = _open(fileName.get(), _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY|_O_SEQUENTIAL, _S_IREAD | _S_IWRITE);
  655. if (h == HFILE_ERROR)
  656. throw MakeStringException(0, "MemoryBuffer: Unable to create file : %s, error=%d", fileName.get(), GetLastError());
  657. CHECKREADPOS(fileSize);
  658. int w;
  659. while (fileSize) {
  660. w = _write(h, buffer+readPos, fileSize);
  661. if (w == 0) {
  662. _close(h);
  663. throw MakeStringException(0, "MemoryBuffer: Disk full writing %d to file : %s", fileSize, fileName.get());
  664. }
  665. if (w == -1)
  666. {
  667. _close(h);
  668. throw MakeStringException(0, "MemoryBuffer: Error writing to file : %s, error=%d", fileName.get(), GetLastError());
  669. }
  670. readPos += (size32_t)w;
  671. fileSize -= (size32_t)w;
  672. }
  673. _close(h);
  674. return *this;
  675. }
  676. MemoryBuffer & MemoryBuffer::rewrite(size32_t pos)
  677. {
  678. assertex(pos<=maxLen);
  679. curLen = pos;
  680. if (readPos>pos)
  681. readPos = pos;
  682. return *this;
  683. }
  684. MemoryBuffer & MemoryBuffer::reset(size32_t pos)
  685. {
  686. CHECKREADPOS(pos-readPos);
  687. readPos = pos;
  688. return *this;
  689. }
  690. #if 0
  691. void MemoryBuffer::getBytes(int srcBegin, int srcEnd, char * target)
  692. {
  693. memcpy(target, buffer + srcBegin, srcEnd - srcBegin);
  694. }
  695. MemoryBuffer & MemoryBuffer::remove(unsigned start, unsigned len)
  696. {
  697. return (MemoryBuffer &)_remove(start, len);
  698. }
  699. #endif
  700. int MemoryBuffer::setEndian(int endian)
  701. {
  702. assertex((endian == __LITTLE_ENDIAN) || (endian == __BIG_ENDIAN));
  703. bool wasSwapped = setSwapEndian(endian != __BYTE_ORDER);
  704. return wasSwapped ? (__BYTE_ORDER ^ __LITTLE_ENDIAN ^ __BIG_ENDIAN) : __BYTE_ORDER;
  705. }
  706. bool MemoryBuffer::setSwapEndian(bool swap)
  707. {
  708. bool saved = swapEndian;
  709. swapEndian = swap;
  710. return saved;
  711. }
  712. MemoryBuffer & serialize(MemoryBuffer & buffer, const MemoryAttr & value)
  713. {
  714. unsigned length = value.length();
  715. buffer.append(length).append(length, value.get());
  716. return buffer;
  717. }
  718. MemoryBuffer & deserialize(MemoryBuffer & buffer, MemoryAttr & value)
  719. {
  720. unsigned length;
  721. buffer.read(length);
  722. void * target = value.allocate(length);
  723. buffer.read(length, target);
  724. return buffer;
  725. }
  726. MemoryBuffer & serialize(MemoryBuffer & buffer, const char * value)
  727. {
  728. if (value)
  729. {
  730. unsigned length = (size32_t)strlen(value);
  731. buffer.append(length).append(length, value);
  732. }
  733. else
  734. buffer.append((unsigned)-1);
  735. return buffer;
  736. }
  737. MemoryBuffer & deserialize(MemoryBuffer & buffer, StringAttr & value)
  738. {
  739. unsigned length;
  740. buffer.read(length);
  741. if (length == (unsigned)-1)
  742. value.clear();
  743. else
  744. {
  745. char * target = (char *)checked_malloc(length+1,-4);
  746. buffer.read(length, target);
  747. target[length] = 0;
  748. value.setown(target);
  749. }
  750. return buffer;
  751. }
  752. // =====================================================================================================
  753. const char * MemoryAttr2IStringVal::str() const
  754. {
  755. UNIMPLEMENTED;
  756. }
  757. // =====================================================================================================
  758. static memsize_t LMsemlimit=0;
  759. static memsize_t LMtotal=0;
  760. static CriticalSection LMsemsect;
  761. static Owned<ILargeMemLimitNotify> LMnotify;
  762. static bool LMlocked = false;
  763. void setLargeMemLimitNotify(memsize_t size,ILargeMemLimitNotify *notify)
  764. {
  765. CriticalBlock block(LMsemsect);
  766. LMsemlimit = size;
  767. LMnotify.set(notify);
  768. if (LMlocked&&(LMtotal<LMsemlimit))
  769. LMlocked = false;
  770. }
  771. inline void incLargeMemTotal(memsize_t sz)
  772. {
  773. if (sz) {
  774. CriticalBlock block(LMsemsect);
  775. LMtotal += sz;
  776. #ifdef TRACE_LARGEMEM
  777. if ((LMtotal/0x100000)!=((LMtotal-sz)/0x100000))
  778. PROGLOG("LARGEMEM(+): %"I64F"d",(offset_t)LMtotal);
  779. #endif
  780. if (!LMlocked&&LMnotify.get()&&(LMtotal>=LMsemlimit)) {
  781. LMlocked = true;
  782. DBGLOG("LargeMemTotal limit exceeded: %"I64F"d",(offset_t)LMtotal);
  783. if (!LMnotify->take(LMtotal)) {
  784. LMtotal -= sz;
  785. LMlocked = false;
  786. throw createOutOfMemException(-9,sz, LMtotal);
  787. }
  788. DBGLOG("LargeMem taken");
  789. }
  790. }
  791. }
  792. inline void decLargeMemTotal(memsize_t sz)
  793. {
  794. if (sz) {
  795. CriticalBlock block(LMsemsect);
  796. LMtotal -= sz;
  797. #ifdef TRACE_LARGEMEM
  798. if ((LMtotal/0x100000)!=((LMtotal+sz)/0x100000))
  799. PROGLOG("LARGEMEM(-): %"I64F"d",(offset_t)LMtotal);
  800. #endif
  801. if (LMlocked) {
  802. if (LMtotal<LMsemlimit) {
  803. DBGLOG("LargeMemTotal limit reduced to %"I64F"d",(offset_t)LMtotal);
  804. LMlocked = false;
  805. if (LMnotify.get())
  806. LMnotify->give(LMtotal);
  807. }
  808. }
  809. }
  810. }
  811. void CLargeMemoryAllocator::allocchunkmem()
  812. {
  813. #ifdef LARGEMEM_USE_MMAP_SIZE
  814. size32_t masize = VMPAGEROUND(chunk.max);
  815. if (masize>=LARGEMEM_USE_MMAP_SIZE) { // use mmap
  816. chunk.base = (byte *) mmap(NULL,masize,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS,-1,0);
  817. if (chunk.base == (byte *)MAP_FAILED)
  818. chunk.base = NULL;
  819. #ifdef TRACE_LARGEMEM_ALLOC
  820. PROGLOG("CLargeMemoryAllocator::allocchunkmem mmaped %d at %p",masize,chunk.base);
  821. #endif
  822. return;
  823. }
  824. #endif
  825. chunk.base = (byte *)malloc(chunk.max);
  826. #ifdef TRACE_LARGEMEM_ALLOC
  827. PROGLOG("CLargeMemoryAllocator::allocchunkmem malloced %d at %p",chunk.max,chunk.base);
  828. #endif
  829. }
  830. void CLargeMemoryAllocator::disposechunkmem()
  831. {
  832. #ifdef LARGEMEM_USE_MMAP_SIZE
  833. size32_t masize = VMPAGEROUND(chunk.max);
  834. if (masize>=LARGEMEM_USE_MMAP_SIZE) { // use mmap
  835. munmap(chunk.base,masize);
  836. return;
  837. }
  838. #endif
  839. free(chunk.base);
  840. }
  841. bool CLargeMemoryAllocator::newchunk(size32_t sz,size32_t extra,bool exceptionwanted)
  842. {
  843. size32_t newchunksz = (sz>chunkmin)?sz:chunkmin;
  844. if (maxallocated()+newchunksz+extra>totalmax) {
  845. #ifdef TRACE_LARGEMEM_OOM
  846. PrintStackReport();
  847. PROGLOG("OOM.1 wanted sz=%d, extra = %d, maxallocated=%"I64F"d, newchunksz=%u, totalmax=%"I64F"d",sz,extra,(offset_t)maxallocated(),newchunksz,(offset_t)totalmax);
  848. #endif
  849. if (exceptionwanted) {
  850. throw createOutOfMemException(-5,sz, maxallocated(),true);
  851. }
  852. return false;
  853. }
  854. if (chunk.size) {
  855. Chunk *p = new Chunk;
  856. *p = chunk;
  857. chunk.prev = p;
  858. atot += chunk.size;
  859. }
  860. else if (chunk.max) {
  861. decLargeMemTotal(chunk.max);
  862. amax -= chunk.max;
  863. disposechunkmem();
  864. }
  865. chunk.max = newchunksz;
  866. allocchunkmem();
  867. chunk.size = 0;
  868. if (!chunk.base) {
  869. // restore prev
  870. if (chunk.prev) {
  871. Chunk *p = chunk.prev;
  872. chunk = *p;
  873. atot -= chunk.size;
  874. delete p;
  875. }
  876. else
  877. chunk.max = 0;
  878. #ifdef TRACE_LARGEMEM_OOM
  879. PrintStackReport();
  880. PROGLOG("OOM.2 wanted sz=%d, extra = %d, maxallocated=%"I64F"d, newchunksz=%u, totalmax=%"I64F"d",sz,extra,(offset_t)maxallocated(),newchunksz,(offset_t)totalmax);
  881. #endif
  882. if (throwexception) {
  883. throw createOutOfMemException(-6,sz, maxallocated(),true);
  884. }
  885. return false;
  886. }
  887. amax += chunk.max;
  888. incLargeMemTotal(newchunksz);
  889. return true;
  890. }
  891. void CLargeMemoryAllocator::reset()
  892. {
  893. decLargeMemTotal(maxallocated());
  894. disposechunkmem();
  895. while (chunk.prev) {
  896. Chunk *p = chunk.prev;
  897. chunk = *chunk.prev;
  898. delete p;
  899. disposechunkmem();
  900. }
  901. chunk.max = 0;
  902. chunk.base = NULL;
  903. chunk.size = 0;
  904. atot = 0;
  905. amax = 0;
  906. }
  907. void CLargeMemoryAllocator::reduceSize(memsize_t amount)
  908. {
  909. if (amount<=chunk.size) {
  910. chunk.size-=amount;
  911. return;
  912. }
  913. memsize_t reduced = 0;
  914. do {
  915. amount -= chunk.size;
  916. reduced += chunk.max;
  917. disposechunkmem();
  918. amax -= chunk.max;
  919. Chunk *p = chunk.prev;
  920. chunk = *p;
  921. atot -= chunk.size;
  922. delete p;
  923. } while (amount>chunk.size);
  924. chunk.size-=amount;
  925. decLargeMemTotal(reduced);
  926. }
  927. void CLargeMemoryAllocator::setSize(memsize_t pos)
  928. {
  929. memsize_t sz = allocated();
  930. assertex(sz>=pos);
  931. reduceSize(sz-pos);
  932. }
  933. byte *CLargeMemoryAllocator::next(memsize_t pos,size32_t &size) // this should not be used for small jumps as it is slow
  934. {
  935. memsize_t sz = allocated();
  936. if (sz<=pos) {
  937. size = 0;
  938. return NULL;
  939. }
  940. memsize_t dif = sz-pos; // how much to go back
  941. Chunk *p = &chunk;
  942. while (dif>p->size) {
  943. dif -= p->size;
  944. p = p->prev;
  945. }
  946. size = (size32_t)dif; // must be smaller than chunk
  947. return p->base+p->size-dif;
  948. }
  949. CLargeMemoryAllocator::CLargeMemoryAllocator()
  950. {
  951. // values overwritten by init
  952. throwexception = true;
  953. totalmax = 0;
  954. chunkmin = 0x1000;
  955. chunk.prev = NULL;
  956. chunk.max = 0;
  957. chunk.base = NULL;
  958. chunk.size = 0;
  959. atot = 0;
  960. amax = 0;
  961. }
  962. void CLargeMemoryAllocator::init(memsize_t _totalmax,size32_t _chunkmin,bool _throwexception)
  963. {
  964. throwexception = _throwexception;
  965. totalmax = _totalmax;
  966. chunkmin = _chunkmin;
  967. chunk.prev = NULL;
  968. chunk.max = 0;
  969. chunk.base = NULL;
  970. chunk.size = 0;
  971. atot = 0;
  972. amax = 0;
  973. }
  974. MemoryBuffer &CLargeMemoryAllocator::serialize(MemoryBuffer &mb)
  975. {
  976. memsize_t al = allocated();
  977. size32_t sz = (size32_t)al;
  978. if (sz!=al)
  979. throw MakeStringException(-1,"CLargeMemoryAllocator::serialize overflow");
  980. byte *d = (byte *)mb.reserveTruncate(sz)+sz;
  981. Chunk *p = &chunk;
  982. while (sz&&p) {
  983. size32_t s = p->size;
  984. d -= s;
  985. memcpy(d,p->base,s);
  986. p = p->prev;
  987. sz -= s;
  988. }
  989. return mb;
  990. }
  991. MemoryBuffer &CLargeMemoryAllocator::deserialize(MemoryBuffer &mb,size32_t sz, size32_t extra)
  992. {
  993. mb.read(sz,alloc(sz,extra));
  994. return mb;
  995. }
  996. void *CLargeMemoryAllocator::nextBuffer(void *prev,size32_t &sz)
  997. { // not fast
  998. Chunk *p = NULL;
  999. Chunk *n = &chunk;
  1000. while (n&&(n->base!=prev)) {
  1001. p = n;
  1002. n = n->prev;
  1003. }
  1004. if (!p) {
  1005. sz = 0;
  1006. return NULL;
  1007. }
  1008. sz = p->size;
  1009. return p->base;
  1010. }
  1011. void CJMallocLargeMemoryAllocator::allocchunkmem()
  1012. {
  1013. chunk.base = (byte *)allocator->allocMem(chunk.max);
  1014. #ifdef TRACE_LARGEMEM_ALLOC
  1015. PROGLOG("CJMallocLargeMemoryAllocator::allocchunkmem malloced %d at %p",chunk.max,chunk.base);
  1016. #endif
  1017. }
  1018. void CJMallocLargeMemoryAllocator::disposechunkmem()
  1019. {
  1020. allocator->freeMem(chunk.base);
  1021. }
  1022. CFixedSizeAllocator::CFixedSizeAllocator()
  1023. {
  1024. chunklist = NULL;
  1025. }
  1026. CFixedSizeAllocator::CFixedSizeAllocator(size32_t _allocsize,size32_t _chunksize)
  1027. {
  1028. chunklist = NULL;
  1029. init(_allocsize,_chunksize);
  1030. }
  1031. void CFixedSizeAllocator::init(size32_t _allocsize,size32_t _chunksize)
  1032. {
  1033. kill();
  1034. allocsize = _allocsize;
  1035. assertex(allocsize);
  1036. if (allocsize<sizeof(void *))
  1037. allocsize = sizeof(void *);
  1038. chunksize = _chunksize;
  1039. if (chunksize<allocsize*16)
  1040. chunksize = allocsize+sizeof(void *); // give up on sublety
  1041. }
  1042. void CFixedSizeAllocator::kill()
  1043. {
  1044. while (chunklist) {
  1045. void *p = chunklist;
  1046. chunklist = *(void **)p;
  1047. freeChunk(p);
  1048. }
  1049. freelist = NULL;
  1050. numalloc = 0;
  1051. numfree = 0;
  1052. chunklist = NULL;
  1053. }
  1054. CFixedSizeAllocator::~CFixedSizeAllocator()
  1055. {
  1056. kill();
  1057. }
  1058. void *CFixedSizeAllocator::allocChunk()
  1059. {
  1060. return checked_malloc(chunksize,-5); // don't try to be clever and allocate less (fragmentation)
  1061. }
  1062. void CFixedSizeAllocator::freeChunk(void *p)
  1063. {
  1064. free(p);
  1065. }
  1066. void *CFixedSizeAllocator::alloc()
  1067. {
  1068. NonReentrantSpinBlock block(lock);
  1069. void *ret;
  1070. if (numfree) {
  1071. numfree--;
  1072. ret = freelist;
  1073. freelist = *(void **)freelist;
  1074. }
  1075. else {
  1076. void **newchunk = (void **)allocChunk();
  1077. unsigned num = (chunksize-sizeof(void *))/allocsize;
  1078. assertex(num);
  1079. *newchunk = chunklist;
  1080. chunklist = (void *)newchunk;
  1081. newchunk++;
  1082. ret = (void *)newchunk;
  1083. numfree+=num-1;
  1084. while (--num) { // we could do this on the fly but I think this marginally better
  1085. newchunk = (void **)(((byte *)newchunk)+allocsize);
  1086. *newchunk = freelist;
  1087. freelist = (void *)newchunk;
  1088. }
  1089. }
  1090. numalloc++;
  1091. return ret;
  1092. }
  1093. void CFixedSizeAllocator::dealloc(void *blk)
  1094. {
  1095. if (blk) {
  1096. NonReentrantSpinBlock block(lock);
  1097. *(void **)blk = freelist;
  1098. freelist = blk;
  1099. numfree++;
  1100. numalloc--;
  1101. }
  1102. }
  1103. void CFixedSizeAllocator::stats(size32_t &sizealloc, size32_t &sizeunused)
  1104. {
  1105. NonReentrantSpinBlock block(lock);
  1106. sizealloc = numalloc*allocsize;
  1107. sizeunused = numfree*allocsize;
  1108. }
  1109. //============================================================
  1110. #define LARGEST_CONTIGUOUS_BLOCK (0xffff0000)
  1111. void CContiguousLargeMemoryAllocator::init(size32_t _totalmax,size32_t _chunkmin,bool _throwexception)
  1112. {
  1113. throwexception = _throwexception;
  1114. totalmax = (_totalmax<LARGEST_CONTIGUOUS_BLOCK)?VMPAGEROUND(_totalmax):LARGEST_CONTIGUOUS_BLOCK;
  1115. chunkmin = _chunkmin;
  1116. ofs = 0;
  1117. mapped = 0;
  1118. base = NULL;
  1119. #ifdef WIN32
  1120. LARGE_INTEGER li;
  1121. li.QuadPart = totalmax;
  1122. hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_RESERVE, li.HighPart, li.LowPart, NULL);
  1123. #endif
  1124. }
  1125. CContiguousLargeMemoryAllocator::CContiguousLargeMemoryAllocator()
  1126. {
  1127. // values overwritten by init
  1128. throwexception = true;
  1129. totalmax = 0;
  1130. chunkmin = 0x1000;
  1131. ofs = 0;
  1132. mapped = 0;
  1133. base = NULL;
  1134. }
  1135. CContiguousLargeMemoryAllocator::~CContiguousLargeMemoryAllocator()
  1136. {
  1137. reset();
  1138. #ifdef WIN32
  1139. if (hmap) {
  1140. if (base)
  1141. UnmapViewOfFile(base);
  1142. CloseHandle(hmap);
  1143. }
  1144. #endif
  1145. }
  1146. void *CContiguousLargeMemoryAllocator::getBase()
  1147. {
  1148. if (!base) {
  1149. #ifdef WIN32
  1150. if (hmap)
  1151. base = (byte *) MapViewOfFile(hmap, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, totalmax);
  1152. else
  1153. base = NULL;
  1154. #else
  1155. base = (byte *) mmap(NULL,totalmax,PROT_NONE,MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS,-1,0);
  1156. // create initially with no access
  1157. if (base == (byte *)MAP_FAILED)
  1158. base = NULL;
  1159. #endif
  1160. }
  1161. return base;
  1162. }
  1163. bool CContiguousLargeMemoryAllocator::map(size32_t tot,size32_t sz)
  1164. {
  1165. getBase();
  1166. if (!base||(tot>totalmax)) {
  1167. outOfMem(sz);
  1168. return false;
  1169. }
  1170. if (tot>mapped) {
  1171. void * a = base+mapped;
  1172. size32_t tomap = VMPAGEROUND(chunkmin);
  1173. #ifdef WIN32
  1174. if (VirtualAlloc(a,tomap,MEM_COMMIT,PAGE_READWRITE)!=a) {
  1175. outOfMem(sz);
  1176. return false;
  1177. }
  1178. #else
  1179. if (mprotect(a,tomap,PROT_READ|PROT_WRITE)<0) {
  1180. int err = errno;
  1181. if ((err==ENOMEM)||(err==EFAULT)) {
  1182. outOfMem(sz);
  1183. return false;
  1184. }
  1185. WARNLOG("CContiguousLargeMemoryAllocator:map madvise err=%d",err);
  1186. }
  1187. #endif
  1188. mapped = mapped+tomap;
  1189. }
  1190. return true;
  1191. }
  1192. void CContiguousLargeMemoryAllocator::unmap()
  1193. {
  1194. // ensures above ofs is unmapped
  1195. size32_t ch = VMPAGEROUND(chunkmin);
  1196. size32_t newmapped = ((ofs+ch-1)/ch)*ch;
  1197. if (newmapped<mapped) {
  1198. void * a = base+newmapped;
  1199. #ifdef WIN32
  1200. if (newmapped==0) { // free completely
  1201. if (base) {
  1202. UnmapViewOfFile(base);
  1203. base = NULL;
  1204. }
  1205. }
  1206. else {
  1207. VirtualFree(a,mapped-newmapped,MEM_DECOMMIT); // can't fail
  1208. }
  1209. #else
  1210. if (newmapped==0) { // free completely
  1211. if (base) {
  1212. munmap(base,totalmax);
  1213. base = NULL;
  1214. }
  1215. }
  1216. else {
  1217. if (mprotect(a,mapped-newmapped,PROT_NONE)<0)
  1218. WARNLOG("CContiguousLargeMemoryAllocator:unmap mprotect err=%d",errno);
  1219. // if (madvise(a,mapped-newmapped,MADV_DONTNEED)<0) // not sure if this does anything but tell it anyway
  1220. // WARNLOG("CContiguousLargeMemoryAllocator:unmap madvise err=%d",errno);
  1221. }
  1222. #endif
  1223. mapped = newmapped;
  1224. }
  1225. }
  1226. void CContiguousLargeMemoryAllocator::reset()
  1227. {
  1228. reduceSize(ofs);
  1229. }
  1230. void CContiguousLargeMemoryAllocator::setSize(size32_t pos)
  1231. {
  1232. assertex(ofs>=pos);
  1233. reduceSize(ofs-pos);
  1234. }
  1235. void CContiguousLargeMemoryAllocator::reduceSize(size32_t amount)
  1236. {
  1237. assertex(ofs>=amount);
  1238. ofs-=amount;
  1239. unmap();
  1240. }
  1241. void *CContiguousLargeMemoryAllocator::nextBuffer(void *prev,size32_t &sz)
  1242. {
  1243. // have to be careful as approaches 4GB
  1244. byte *p = prev?((byte *)prev):base;
  1245. size32_t o = p-base;
  1246. size32_t r = (o<ofs)?ofs-o:0;
  1247. sz = (r<=chunkmin)?0:(r-chunkmin);
  1248. if (sz==0)
  1249. return NULL;
  1250. if (sz>chunkmin)
  1251. sz = chunkmin;
  1252. return p+chunkmin;
  1253. }
  1254. byte *CContiguousLargeMemoryAllocator::next(size32_t pos,size32_t &size)
  1255. {
  1256. if (ofs<=pos) {
  1257. size = 0;
  1258. return NULL;
  1259. }
  1260. size = ofs-pos;
  1261. return base+pos;
  1262. }
  1263. MemoryBuffer &CContiguousLargeMemoryAllocator::serialize(MemoryBuffer &mb)
  1264. {
  1265. memcpy(mb.reserveTruncate(ofs),base,ofs);
  1266. return mb;
  1267. }
  1268. MemoryBuffer &CContiguousLargeMemoryAllocator::deserialize(MemoryBuffer &mb,size32_t sz, size32_t extra)
  1269. {
  1270. mb.read(sz,alloc(sz,extra));
  1271. return mb;
  1272. }
  1273. void CContiguousLargeMemoryAllocator::outOfMem(size32_t sz)
  1274. {
  1275. if (throwexception) {
  1276. throw createOutOfMemException(-6,sz, ofs,true);
  1277. }
  1278. }