1//===- TreeAllocator.h ----------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#ifndef MCLD_TREE_ALLOCATOR_H 10#define MCLD_TREE_ALLOCATOR_H 11#ifdef ENABLE_UNITTEST 12#include <gtest.h> 13#endif 14#include <set> 15#include "mcld/Support/GCFactory.h" 16 17namespace mcld { 18 19/** \class NodeFactory 20 * \brief NodeFactory manages the creation and destruction of mcld::Node. 21 * 22 * NodeFactory guarantees all allocated memory are released finally. When 23 * the destructor of NodeFactory is called, all allocated memory are freed. 24 * 25 * NodeFactory provides delegation of memory. Sometimes, we have to merge two 26 * NodeFactories, and NodeFactory::delegate() can move the memory from one 27 * NodeFactories to another. 28 * 29 * @see LinearAllocator 30 */ 31template<typename DataType> 32class NodeFactory : public GCFactory<Node<DataType>, 64> 33{ 34private: 35 typedef GCFactory<Node<DataType>, 64> Alloc; 36 37public: 38 typedef Node<DataType> NodeType; 39 typedef typename Alloc::iterator iterator; 40 typedef typename Alloc::const_iterator const_iterator; 41 42public: 43 /// produce - produce a node, add it under control 44 NodeType* produce() { 45 NodeType* result = Alloc::allocate(); 46 Alloc::construct(result); 47 return result; 48 } 49 50 /// delegate - get the control of chunks owned by the client 51 // after calling delegate(), client will renouce its control 52 // of memory space. 53 void delegate(NodeFactory& pClient) { 54 if (this == &pClient) 55 return; 56 57 if (pClient.empty()) 58 return; 59 60 if (Alloc::empty()) { 61 replace(pClient); 62 pClient.renounce(); 63 return; 64 } 65 66 // neither me nor client is empty 67 concatenate(pClient); 68 pClient.renounce(); 69 } 70 71private: 72 /// renounce - give up the control of all chunks 73 void renounce() 74 { Alloc::reset(); } 75 76 /// replace - be the agent of client. 77 void replace(NodeFactory& pClient) { 78 Alloc::m_pRoot = pClient.Alloc::m_pRoot; 79 Alloc::m_pCurrent = pClient.Alloc::m_pCurrent; 80 Alloc::m_AllocatedNum = pClient.Alloc::m_AllocatedNum; 81 Alloc::m_NumAllocData = pClient.Alloc::m_NumAllocData; 82 } 83 84 /// concatenate - conncet two factories 85 void concatenate(NodeFactory& pClient) { 86 Alloc::m_pCurrent->next = pClient.Alloc::m_pRoot; 87 Alloc::m_pCurrent = pClient.Alloc::m_pCurrent; 88 Alloc::m_AllocatedNum += pClient.Alloc::m_AllocatedNum; 89 Alloc::m_NumAllocData += pClient.Alloc::m_NumAllocData; 90 } 91}; 92 93} // namespace of mcld 94 95#endif 96 97