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