Advertisement
Guest User

Untitled

a guest
Mar 2nd, 2015
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.44 KB | None | 0 0
  1.  
  2. #include "ObjectAllocator.h"
  3.  
  4. // initialization of static variable
  5. const int ObjectAllocator::FLAGS_SIZE = 1;
  6. const int ObjectAllocator::ALLOCATION_SIZE = 4;
  7. const int ObjectAllocator::USE_COUNTER_SIZE = 2;
  8.  
  9. /******************************************************************************/
  10. /*!
  11. \brief
  12. Constructor for ObjectAllocator class
  13.  
  14. \param ObjectSize
  15. Size of each object
  16. \param config
  17. Configuration of the object allocator
  18. */
  19. /******************************************************************************/
  20. ObjectAllocator::ObjectAllocator(size_t ObjectSize, const OAConfig& config)
  21. throw(OAException) :
  22. _blockSize(0), _pageHeadSize(0), _ptrSize(sizeof(void*)),
  23. _hasInternalHeader(false), _hasAlignment(false)
  24. {
  25. // initialize the OA base on the config
  26. InitHeaderConfig(config);
  27.  
  28. _config = config;
  29. _stats.ObjectSize_ = ObjectSize;
  30. _blockSize = static_cast<unsigned>(ObjectSize) +
  31. 2 * config.PadBytes_ + _headerSize;
  32. _pageHeadSize = _ptrSize + _headerSize + config.PadBytes_;
  33. _stats.PageSize_ = _ptrSize + (config.ObjectsPerPage_ * _blockSize);
  34.  
  35.  
  36. // calculate the alignment based on the config
  37. CalculateAlignment(config);
  38.  
  39. // create an initial page for the OA
  40. try
  41. {
  42. _pageList = CreatePage();
  43. reinterpret_cast<GenericObject*>(_pageList)->Next = 0;
  44. }
  45. catch (std::bad_alloc&)
  46. {
  47. throw OAException(OAException::E_NO_MEMORY, "The system is out of memory.");
  48. }
  49. }
  50.  
  51. /******************************************************************************/
  52. /*!
  53. \brief
  54. Init the header configuration based on the input config
  55.  
  56. \param config
  57. Configuration of the object allocator
  58. */
  59. /******************************************************************************/
  60. void ObjectAllocator::InitHeaderConfig(const OAConfig& config)
  61. {
  62. // Initializae header size and whether if internal header exists
  63. switch (config.HBlockInfo_.type_)
  64. {
  65. case OAConfig::hbBasic:
  66. _headerSize = config.BASIC_HEADER_SIZE;
  67. _hasInternalHeader = true;
  68. break;
  69. case OAConfig::hbExtended:
  70. _headerSize = static_cast<unsigned>(config.HBlockInfo_.size_);
  71. _hasInternalHeader = true;
  72. break;
  73. case OAConfig::hbExternal:
  74. _headerSize = config.EXTERNAL_HEADER_SIZE;
  75. _hasInternalHeader = false;
  76. break;
  77. default:
  78. _headerSize = 0;
  79. _hasInternalHeader = false;
  80. break;
  81. }
  82. }
  83.  
  84. /******************************************************************************/
  85. /*!
  86. \brief
  87. Calculate the alignment
  88.  
  89. \param config
  90. Configuration of the object allocator
  91. */
  92. /******************************************************************************/
  93. void ObjectAllocator::CalculateAlignment(const OAConfig& config)
  94. {
  95. // do not check if alignment is 1
  96. if (config.Alignment_ <= 1)
  97. return;
  98.  
  99. // compute left alignment
  100. if (config.Alignment_ >= _pageHeadSize)
  101. _config.LeftAlignSize_ = config.Alignment_ - _pageHeadSize;
  102. else
  103. {
  104. unsigned tmp = config.Alignment_;
  105. while (tmp < _pageHeadSize)
  106. tmp += config.Alignment_;
  107.  
  108. _config.LeftAlignSize_ = tmp - _pageHeadSize;
  109. }
  110.  
  111. _pageHeadSize += _config.LeftAlignSize_;
  112.  
  113. // compute inter alignment
  114. if (config.Alignment_ >= _blockSize)
  115. _config.InterAlignSize_ = config.Alignment_ % _blockSize;
  116. else
  117. {
  118. unsigned tmp = config.Alignment_;
  119. while (tmp < _blockSize)
  120. tmp += config.Alignment_;
  121.  
  122. _config.InterAlignSize_ = tmp - _blockSize;
  123. }
  124.  
  125. _blockSize += _config.InterAlignSize_;
  126.  
  127. // compute the new size of each page
  128. _stats.PageSize_ = _ptrSize + _config.LeftAlignSize_ +
  129. config.ObjectsPerPage_ * _blockSize - _config.InterAlignSize_;
  130.  
  131. _hasAlignment = true;
  132. }
  133.  
  134. /******************************************************************************/
  135. /*!
  136. \brief
  137. Allocate memory for a page
  138. */
  139. /******************************************************************************/
  140. char* ObjectAllocator::CreatePage()
  141. {
  142. // allocate memory on the freestore
  143. char* page = new char[_stats.PageSize_];
  144. // memset pattern of unallocated
  145. std::memset(page, UNALLOCATED_PATTERN, _stats.PageSize_);
  146. reinterpret_cast<GenericObject*>(page)->Next = 0;
  147.  
  148. // if left alignment exists, memset alignment pattern
  149. if (_hasAlignment)
  150. {
  151. char* LeftAlignPtr = page + _ptrSize;
  152. std::memset(LeftAlignPtr, ALIGN_PATTERN, _config.LeftAlignSize_);
  153. }
  154.  
  155. _freeList = page + _pageHeadSize;
  156. reinterpret_cast<GenericObject*>(_freeList)->Next = NULL;
  157.  
  158. // memset pattern of padding
  159. std::memset(_freeList - _config.PadBytes_, PAD_PATTERN, _config.PadBytes_);
  160. std::memset(_freeList - _config.PadBytes_ - _headerSize, 0, _headerSize);
  161.  
  162. // initialize each block in the page for usage
  163. InitBlock();
  164.  
  165. // memset pattern of padding of back
  166. std::memset(_freeList + _stats.ObjectSize_, PAD_PATTERN, _config.PadBytes_);
  167.  
  168. _stats.FreeObjects_ += _config.ObjectsPerPage_;
  169. ++_stats.PagesInUse_;
  170.  
  171. return page;
  172. }
  173.  
  174. /******************************************************************************/
  175. /*!
  176. \brief
  177. Initialize the block on the page
  178. */
  179. /******************************************************************************/
  180. void ObjectAllocator::InitBlock()
  181. {
  182. for (unsigned i = 0; i < _config.ObjectsPerPage_ - 1; ++i)
  183. {
  184. char* tmp = _freeList; // keep a temp for linkage
  185. // memset pattern of padding
  186. std::memset(_freeList + _stats.ObjectSize_, PAD_PATTERN, _config.PadBytes_);
  187.  
  188. // memset pattern of inter alignment if exists
  189. if (_hasAlignment)
  190. std::memset(_freeList + _stats.ObjectSize_ + _config.PadBytes_,
  191. ALIGN_PATTERN, _config.InterAlignSize_);
  192.  
  193. _freeList += _blockSize;
  194.  
  195. // memset pattern for padding
  196. std::memset(_freeList - _config.PadBytes_, PAD_PATTERN, _config.PadBytes_);
  197. // memset pattern for header
  198. std::memset(_freeList - _config.PadBytes_ - _headerSize, 0, _headerSize);
  199.  
  200. // handle linkage to the previous freeList
  201. reinterpret_cast<GenericObject*>(_freeList)->Next =
  202. reinterpret_cast<GenericObject*>(tmp);
  203. }
  204. }
  205.  
  206. /******************************************************************************/
  207. /*!
  208. \brief
  209. Destructor for ObjectAllocator class
  210. */
  211. /******************************************************************************/
  212. ObjectAllocator::~ObjectAllocator() throw()
  213. {
  214. // loop through all the pages and free all the header that was allocated
  215. while (_pageList)
  216. {
  217. char * nextPage =
  218. reinterpret_cast<char *>(reinterpret_cast<GenericObject*>(_pageList)->Next);
  219.  
  220. RemovePageHeader();
  221. RemoveInterblockHeader();
  222.  
  223. delete [] _pageList;
  224. _pageList = nextPage; // move to next page
  225.  
  226. }
  227. }
  228.  
  229. /******************************************************************************/
  230. /*!
  231. \brief
  232. Constructor for ObjectAllocator class
  233.  
  234. \param label
  235. Label for the header block
  236. */
  237. /******************************************************************************/
  238. void * ObjectAllocator::Allocate(const char *label) throw(OAException)
  239. {
  240. if (_config.UseCPPMemManager_)
  241. return CPPNew();
  242.  
  243. // check if any more objects can be allocated
  244. CheckMaxObjects();
  245.  
  246. char * freeBlock = _freeList;
  247. ++_stats.Allocations_;
  248.  
  249. // check if the current page is full
  250. CheckFullPage(&freeBlock);
  251.  
  252. // init block header
  253. if (_hasInternalHeader)
  254. InitInternalHeader();
  255. else if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  256. InitExternalHeader(label);
  257.  
  258. _freeList =
  259. reinterpret_cast<char *>(reinterpret_cast<GenericObject *>(_freeList)->Next);
  260.  
  261. // memset pattern for allocated
  262. std::memset(freeBlock, ALLOCATED_PATTERN, _stats.ObjectSize_);
  263.  
  264. // modify stats
  265. ++_stats.ObjectsInUse_;
  266. ++_stats.MostObjects_;
  267. --_stats.FreeObjects_;
  268.  
  269. return freeBlock;
  270. }
  271.  
  272. /******************************************************************************/
  273. /*!
  274. \brief
  275. Allocate block using C++ lib new
  276. */
  277. /******************************************************************************/
  278. void * ObjectAllocator::CPPNew() throw (OAException)
  279. {
  280. try
  281. {
  282. char * newBlock = new char[_stats.ObjectSize_];
  283. ++_stats.Allocations_;
  284. ++_stats.MostObjects_;
  285. --_stats.FreeObjects_;
  286. return newBlock;
  287. }
  288. catch (std::bad_alloc&)
  289. {
  290. throw OAException(OAException::E_NO_MEMORY, "The system is out of memory.");
  291. }
  292. }
  293.  
  294. /******************************************************************************/
  295. /*!
  296. \brief
  297. Check if the OA has reached its maximum cap
  298. */
  299. /******************************************************************************/
  300. void ObjectAllocator::CheckMaxObjects() throw (OAException)
  301. {
  302. if (!_config.MaxPages_)
  303. return;
  304.  
  305. // check if any more objects can be allocated
  306. if (_stats.ObjectsInUse_ >= _config.MaxPages_ * _config.ObjectsPerPage_)
  307. throw OAException(OAException::E_NO_PAGES, "Reached max objects.");
  308. }
  309.  
  310. /******************************************************************************/
  311. /*!
  312. \brief
  313. Check if the page is full
  314.  
  315. \param block
  316. Pointer to the last block of the page
  317. */
  318. /******************************************************************************/
  319. void ObjectAllocator::CheckFullPage(char ** block) throw (OAException)
  320. {
  321. if (*block) // if block != null, page not full
  322. return;
  323.  
  324. // try to allocate memory for a new page
  325. try
  326. {
  327. *block = CreatePage();
  328. reinterpret_cast<GenericObject *>(*block)->Next =
  329. reinterpret_cast<GenericObject *>(_pageList);
  330. _pageList = reinterpret_cast<char *>(*block);
  331. }
  332. catch (std::bad_alloc&)
  333. {
  334. throw OAException(OAException::E_NO_MEMORY, "The system is out of memory.");
  335. }
  336.  
  337. *block = _freeList;
  338. }
  339.  
  340. /******************************************************************************/
  341. /*!
  342. \brief
  343. Initialize the internal header of the page
  344. */
  345. /******************************************************************************/
  346. void ObjectAllocator::InitInternalHeader()
  347. {
  348. // pointer to the header
  349. char * header = _freeList - _config.PadBytes_ - _headerSize;
  350.  
  351. // init header base on config
  352. if (_config.HBlockInfo_.type_ == OAConfig::hbBasic)
  353. {
  354. *(header + ALLOCATION_SIZE) = 1;
  355. *reinterpret_cast<unsigned *>(header) = _stats.Allocations_;
  356. }
  357. else if (_config.HBlockInfo_.type_ == OAConfig::hbExtended)
  358. {
  359. ++*(header + _headerSize - FLAGS_SIZE -
  360. ALLOCATION_SIZE - USE_COUNTER_SIZE);
  361. *(header + _headerSize - FLAGS_SIZE) = 1;
  362. *reinterpret_cast<unsigned *>(
  363. header + _headerSize - FLAGS_SIZE - ALLOCATION_SIZE) = _stats.Allocations_;
  364. }
  365. }
  366.  
  367. /******************************************************************************/
  368. /*!
  369. \brief
  370. Initialize the external header of the page
  371.  
  372. \param label
  373. Label used to initialize the external header with
  374. */
  375. /******************************************************************************/
  376. void ObjectAllocator::InitExternalHeader(const char * label) throw(OAException)
  377. {
  378. // create header info for block
  379. char* header;
  380. try
  381. {
  382. header = new char[sizeof(MemBlockInfo)];
  383. }
  384. catch (std::bad_alloc&)
  385. {
  386. throw OAException(OAException::E_NO_MEMORY, "The system is out of memory.");
  387. }
  388.  
  389. reinterpret_cast<MemBlockInfo*>(header)->in_use = true;
  390.  
  391. reinterpret_cast<MemBlockInfo*>(header)->alloc_num = _stats.Allocations_;
  392.  
  393. // allocate memory for label if needed
  394. if (label)
  395. {
  396. reinterpret_cast<MemBlockInfo*>(header)->label= new char[strlen(label) + 1];
  397. strcpy(reinterpret_cast<MemBlockInfo*>(header)->label, label);
  398. }
  399. else
  400. reinterpret_cast<MemBlockInfo*>(header)->label = 0;
  401.  
  402. // set header info to block's header
  403. *(reinterpret_cast<MemBlockInfo**>(_freeList-_config.PadBytes_-_headerSize)) =
  404. reinterpret_cast<MemBlockInfo *>(header);
  405. }
  406.  
  407. /******************************************************************************/
  408. /*!
  409. \brief
  410. Free the object
  411.  
  412. \param Object
  413. Pointer to the block to be freed
  414. */
  415. /******************************************************************************/
  416. void ObjectAllocator::Free(void * Object) throw(OAException)
  417. {
  418. if (!Object)
  419. return;
  420.  
  421. if (_config.UseCPPMemManager_)
  422. {
  423. CPPDelete(Object);
  424. return;
  425. }
  426.  
  427. // an exception will be thrown if object not valid
  428. if (_config.DebugOn_)
  429. ValidateFree(Object);
  430.  
  431. if (_hasInternalHeader)
  432. RemoveInternalHeader(Object);
  433. else if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  434. RemoveExternalHeader(Object);
  435. }
  436.  
  437. /******************************************************************************/
  438. /*!
  439. \brief
  440. Check if the free call is valid
  441.  
  442. \param Object
  443. Pointer to the block to be freed
  444. */
  445. /******************************************************************************/
  446. void ObjectAllocator::ValidateFree(void * Object) throw(OAException)
  447. {
  448. // validate free by checking boundary and multiple freeing
  449. CheckBadBoundary(Object);
  450. CheckMultipleFree(Object);
  451.  
  452. if (_config.PadBytes_)
  453. CheckCorruptedBlock(Object);
  454.  
  455. // remove headers
  456. if (_hasInternalHeader)
  457. RemoveInternalHeader(Object);
  458. else if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  459. RemoveExternalHeader(Object);
  460.  
  461. // memset pattern for freed
  462. std::memset(Object, FREED_PATTERN, _stats.ObjectSize_);
  463.  
  464. // relink the freelist pointer
  465. GenericObject * tmp = reinterpret_cast<GenericObject*>(_freeList);
  466. _freeList = reinterpret_cast<char *>(Object);
  467. reinterpret_cast<GenericObject *>(_freeList)->Next = tmp;
  468.  
  469. ++_stats.Deallocations_;
  470. ++_stats.FreeObjects_;
  471. --_stats.ObjectsInUse_;
  472. }
  473.  
  474. /******************************************************************************/
  475. /*!
  476. \brief
  477. Check if the location to be freed is in bad bounds
  478.  
  479. \param Object
  480. Pointer to the block to be freed
  481. */
  482. /******************************************************************************/
  483. void ObjectAllocator::CheckBadBoundary(void * Object) throw(OAException)
  484. {
  485. char * currPage = _pageList;
  486.  
  487. while (currPage)
  488. {
  489. char * pageStart = currPage + _pageHeadSize;
  490. unsigned pageAdd = reinterpret_cast<unsigned>(currPage);
  491. unsigned objAdd = reinterpret_cast<unsigned>(Object);
  492.  
  493. // check if object is within the page
  494. if (objAdd - pageAdd < _stats.PageSize_)
  495. {
  496. unsigned offset = reinterpret_cast<char *>(Object) - pageStart;
  497.  
  498. // check if the object is aligned
  499. if (!(offset % _blockSize))
  500. return;
  501. }
  502.  
  503. currPage = reinterpret_cast<char *>(
  504. reinterpret_cast<GenericObject *>(currPage)->Next);
  505. }
  506.  
  507. // throw an exception if reaches to this point, meaning it is not aligned
  508. throw OAException(OAException::E_BAD_BOUNDARY,
  509. "Trying to free an object in a bad boundary.");
  510. }
  511.  
  512. /******************************************************************************/
  513. /*!
  514. \brief
  515. Check if the current location has been freed
  516.  
  517. \param Object
  518. Pointer to the block to be freed
  519. */
  520. /******************************************************************************/
  521. void ObjectAllocator::CheckMultipleFree(void * Object) throw(OAException)
  522. {
  523. GenericObject * tmp = reinterpret_cast<GenericObject *>(_freeList);
  524.  
  525. // check if object that we are freeing is already in the free list
  526. while (tmp)
  527. {
  528. if (Object == tmp)
  529. throw OAException(OAException::E_MULTIPLE_FREE,
  530. "Trying to free an object multiple times.");
  531.  
  532. tmp = tmp->Next;
  533. }
  534. }
  535.  
  536. /******************************************************************************/
  537. /*!
  538. \brief
  539. Check if the location to be freed is corrupted
  540.  
  541. \param Object
  542. Pointer to the block to be freed
  543. */
  544. /******************************************************************************/
  545. void ObjectAllocator::CheckCorruptedBlock(void * Object) throw(OAException)
  546. {
  547. unsigned char * tmp = reinterpret_cast<unsigned char *>(Object);
  548. // loop through and check if padding are corrupted block
  549. for (unsigned i = 0; i < _config.PadBytes_; i++)
  550. {
  551. if (*(tmp - _config.PadBytes_ + i) != PAD_PATTERN ||
  552. *(tmp + _stats.ObjectSize_ + i) != PAD_PATTERN)
  553. throw OAException(OAException::E_CORRUPTED_BLOCK,
  554. "Trying to free a corrupted block");
  555. }
  556. }
  557.  
  558. /******************************************************************************/
  559. /*!
  560. \brief
  561. Remove the internal header of the block
  562.  
  563. \param Object
  564. Pointer to the block to be freed
  565. */
  566. /******************************************************************************/
  567. void ObjectAllocator::RemoveInternalHeader(void * Object) throw(OAException)
  568. {
  569. char * header = reinterpret_cast<char*>(Object)-_config.PadBytes_-_headerSize;
  570.  
  571. // Reset the data in the internal header
  572. if (_config.HBlockInfo_.type_ == OAConfig::hbBasic)
  573. {
  574. *(header + _headerSize - FLAGS_SIZE) = 0;
  575. *reinterpret_cast<unsigned *>(header) = 0;
  576. }
  577. else if (_config.HBlockInfo_.type_ == OAConfig::hbExtended)
  578. {
  579. *(header + _headerSize - FLAGS_SIZE) = 0;
  580. *reinterpret_cast<unsigned *>(
  581. header + _headerSize - FLAGS_SIZE - ALLOCATION_SIZE) = 0;
  582. }
  583. }
  584.  
  585. /******************************************************************************/
  586. /*!
  587. \brief
  588. Free the memory allocated for the external header
  589.  
  590. \param Object
  591. Pointer to the block to be freed
  592. */
  593. /******************************************************************************/
  594. void ObjectAllocator::RemoveExternalHeader(void * Object) throw(OAException)
  595. {
  596. char * header = reinterpret_cast<char *>(Object) -
  597. _config.PadBytes_ - _headerSize;
  598. MemBlockInfo * blockInfo =
  599. reinterpret_cast<MemBlockInfo *>(*reinterpret_cast<MemBlockInfo **>(header));
  600.  
  601. blockInfo->in_use = false;
  602. delete [] blockInfo->label;
  603. blockInfo->label = 0;
  604. }
  605.  
  606. /******************************************************************************/
  607. /*!
  608. \brief
  609. Free memory allocated for the page header
  610. */
  611. /******************************************************************************/
  612. void ObjectAllocator::RemovePageHeader()
  613. {
  614. char * tmp = _pageList + _pageHeadSize - _config.PadBytes_ - _headerSize;
  615.  
  616. if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  617. {
  618. MemBlockInfo *& blockInfo = *reinterpret_cast<MemBlockInfo **>(tmp);
  619. if (blockInfo)
  620. {
  621. if (blockInfo->label)
  622. delete[] blockInfo->label;
  623. delete[] blockInfo;
  624. blockInfo = 0;
  625. }
  626. }
  627. }
  628.  
  629. /******************************************************************************/
  630. /*!
  631. \brief
  632. Free the memory allocated for the inter block header
  633. */
  634. /******************************************************************************/
  635. void ObjectAllocator::RemoveInterblockHeader()
  636. {
  637. char* currHeader = _pageList + _pageHeadSize + _blockSize -
  638. _config.PadBytes_ - _headerSize;
  639.  
  640. // loop through and free the inter block header
  641. for (unsigned i = 0; i < _config.ObjectsPerPage_ - 1; ++i)
  642. {
  643. char * tmp = reinterpret_cast<char*>(currHeader) + _blockSize;
  644.  
  645. if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  646. {
  647. MemBlockInfo *& info = *(reinterpret_cast<MemBlockInfo **>(currHeader));
  648.  
  649. if (info)
  650. {
  651. if (info->label)
  652. delete[] info->label;
  653. delete[] info;
  654. info = 0;
  655. }
  656. }
  657.  
  658. currHeader = tmp;
  659. }
  660. }
  661.  
  662. /******************************************************************************/
  663. /*!
  664. \brief
  665. Free the object using the c++ lib delete
  666.  
  667. \param Object
  668. Pointer to the block to be freed
  669. */
  670. /******************************************************************************/
  671. void ObjectAllocator::CPPDelete(void * Object)
  672. {
  673. delete [] reinterpret_cast<char *>(Object);
  674. ++_stats.Deallocations_;
  675. ++_stats.FreeObjects_;
  676. --_stats.ObjectsInUse_;
  677. }
  678.  
  679. /******************************************************************************/
  680. /*!
  681. \brief
  682. Dump memory of all the block that are still in use
  683.  
  684. \param fn
  685. Function callback used to dump the memory
  686. */
  687. /******************************************************************************/
  688. unsigned ObjectAllocator::DumpMemoryInUse(DUMPCALLBACK fn) const
  689. {
  690. unsigned leakCounter = 0;
  691. GenericObject * currPage = reinterpret_cast<GenericObject *>(_pageList);
  692.  
  693. // loop through all the pages and dump the memory
  694. while (currPage)
  695. {
  696. unsigned char * pageStart =
  697. reinterpret_cast<unsigned char *>(currPage) + _pageHeadSize;
  698.  
  699. for (unsigned i = 0; i < _config.ObjectsPerPage_; ++i)
  700. {
  701. // dump memory of block still in use
  702. if (*pageStart == ALLOCATED_PATTERN)
  703. {
  704. fn(pageStart, _stats.ObjectSize_);
  705. ++leakCounter;
  706. }
  707.  
  708. if (i != _config.ObjectsPerPage_ - 1) pageStart += _blockSize;
  709. }
  710.  
  711. currPage = currPage->Next;
  712. }
  713.  
  714. return leakCounter;
  715. }
  716.  
  717. /******************************************************************************/
  718. /*!
  719. \brief
  720. Validate the pages
  721.  
  722. \param fn
  723. Function callback to validate the pages
  724. */
  725. /******************************************************************************/
  726. unsigned ObjectAllocator::ValidatePages(VALIDATECALLBACK fn) const
  727. {
  728. unsigned corruptCounter = 0;
  729. GenericObject * currPage = reinterpret_cast<GenericObject *>(_pageList);
  730.  
  731. while (currPage)
  732. {
  733. char * pageStart = reinterpret_cast<char *>(currPage) + _pageHeadSize;
  734.  
  735. // loop to check current page
  736. for (unsigned i = 0; i < _config.ObjectsPerPage_; ++i)
  737. {
  738. // check for corrupted padding boundaries
  739. unsigned char * pad = reinterpret_cast<unsigned char *>(pageStart);
  740.  
  741. for (unsigned j = 0; j < _config.PadBytes_; ++j)
  742. {
  743. // left padding
  744. if (*(pad - _config.PadBytes_ + j) != PAD_PATTERN)
  745. {
  746. fn(pad, _stats.ObjectSize_);
  747. ++corruptCounter;
  748. break;
  749. }
  750.  
  751. // right padding
  752. if (*(pad + _stats.ObjectSize_ + j) != PAD_PATTERN)
  753. {
  754. fn(pad, _stats.ObjectSize_);
  755. ++corruptCounter;
  756. break;
  757. }
  758. }
  759.  
  760. if (i != _config.ObjectsPerPage_ - 1)
  761. pageStart += _blockSize;
  762. }
  763.  
  764. currPage = currPage->Next;
  765. }
  766.  
  767. return corruptCounter;
  768. }
  769.  
  770. /******************************************************************************/
  771. /*!
  772. \brief
  773. Free the memory allocated if the page is empty and not in use
  774.  
  775. \return
  776. Number of pages freed
  777. */
  778. /******************************************************************************/
  779. unsigned ObjectAllocator::FreeEmptyPages(void)
  780. {
  781. unsigned count = 0;
  782.  
  783. GenericObject *prevPage = reinterpret_cast<GenericObject *>(_pageList);
  784. GenericObject *currPage = reinterpret_cast<GenericObject *>(_pageList);
  785.  
  786. // loop through all pages
  787. while (currPage)
  788. {
  789. bool isEmpty = true;
  790. unsigned offset = _pageHeadSize;
  791.  
  792. // loop through all objects
  793. for (unsigned i = 0 ; i < _config.ObjectsPerPage_ ; ++i)
  794. {
  795. bool isFound = false;
  796.  
  797. GenericObject *currFree = reinterpret_cast<GenericObject *>(_freeList);
  798.  
  799. // loop through free list
  800. while (currFree)
  801. {
  802. if (reinterpret_cast<char *>(currPage) + offset ==
  803. reinterpret_cast<char*>(currFree))
  804. {
  805. isFound = true;
  806. break;
  807. }
  808.  
  809. currFree = currFree->Next;
  810. }
  811.  
  812. // found object that exists in the page from the free list
  813. if (!isFound)
  814. {
  815. isEmpty = false;
  816. break;
  817. }
  818.  
  819. offset += _blockSize;
  820. }
  821.  
  822. // clear page if empty
  823. if (isEmpty)
  824. {
  825. --_stats.PagesInUse_;
  826. _stats.FreeObjects_ -= _config.ObjectsPerPage_;
  827. ++count;
  828.  
  829. // rebuild free list
  830. GenericObject *prevFree = reinterpret_cast<GenericObject *>(_freeList);
  831. GenericObject *currFree = reinterpret_cast<GenericObject *>(_freeList);
  832.  
  833. // loop through the free list
  834. while (currFree)
  835. {
  836. // found in current page
  837. if (currPage < currFree &&
  838. reinterpret_cast<char *>(currPage) + _stats.PageSize_ >
  839. reinterpret_cast<char *>(currFree))
  840. {
  841. if (reinterpret_cast<char *>(currFree) == _freeList)
  842. _freeList = reinterpret_cast<char *>(currFree->Next);
  843. else
  844. prevFree->Next = currFree->Next;
  845. }
  846. else
  847. prevFree = currFree;
  848.  
  849. currFree = currFree->Next;
  850. }
  851.  
  852. // relink previous page to next page
  853. if (reinterpret_cast<char *>(currPage) == _pageList)
  854. _pageList = reinterpret_cast<char *>(currPage->Next);
  855. else
  856. prevPage->Next = currPage->Next;
  857.  
  858. if (_config.HBlockInfo_.type_ == OAConfig::hbExternal)
  859. {
  860. RemovePageHeader();
  861. RemoveInterblockHeader();
  862. }
  863.  
  864. // delete page
  865. GenericObject* temp = currPage;
  866. currPage = currPage->Next;
  867. delete[] temp;
  868.  
  869. }
  870. else
  871. {
  872. prevPage = currPage;
  873. currPage = currPage->Next;
  874. }
  875. }
  876.  
  877. return count;
  878. }
  879.  
  880. /******************************************************************************/
  881. /*!
  882. \brief
  883. Check if the location to be freed is in bad bounds
  884.  
  885. \return
  886. Return true if implemented extra credits, false if otherwise
  887. */
  888. /******************************************************************************/
  889. bool ObjectAllocator::ImplementedExtraCredit(void)
  890. {
  891. return true;
  892. }
  893.  
  894. /******************************************************************************/
  895. /*!
  896. \brief
  897. Set the config debug state
  898.  
  899. \param State
  900. Boolean to on/off the debug state
  901. */
  902. /******************************************************************************/
  903. void ObjectAllocator::SetDebugState(bool State)
  904. {
  905. _config.DebugOn_ = State;
  906. }
  907.  
  908. /******************************************************************************/
  909. /*!
  910. \brief
  911. Get pointer to the free list
  912.  
  913. \return
  914. Pointer to the free list of the OA
  915. */
  916. /******************************************************************************/
  917. const void* ObjectAllocator::GetFreeList(void) const
  918. {
  919. return _freeList;
  920. }
  921.  
  922. /******************************************************************************/
  923. /*!
  924. \brief
  925. Get pointer to the page list
  926.  
  927. \return
  928. Pointer to the page list of the OA
  929. */
  930. /******************************************************************************/
  931. const void* ObjectAllocator::GetPageList(void) const
  932. {
  933. return _pageList;
  934. }
  935.  
  936. /******************************************************************************/
  937. /*!
  938. \brief
  939. Get the config for the OA
  940.  
  941. \return
  942. Config of the OA
  943. */
  944. /******************************************************************************/
  945. OAConfig ObjectAllocator::GetConfig(void) const
  946. {
  947. return _config;
  948. }
  949.  
  950. /******************************************************************************/
  951. /*!
  952. \brief
  953. Get the stats of the OA
  954.  
  955. \return
  956. Stats of the OA
  957. */
  958. /******************************************************************************/
  959. OAStats ObjectAllocator::GetStats(void) const
  960. {
  961. return _stats;
  962. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement