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 12 #include "mcld/ADT/TreeBase.h" 13 #include "mcld/Support/GCFactory.h" 14 15 #include <set> 16 17 namespace 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 */ 31 template <typename DataType> 32 class NodeFactory : public GCFactory<Node<DataType>, 64> { 33 private: 34 typedef GCFactory<Node<DataType>, 64> Alloc; 35 36 public: 37 typedef Node<DataType> NodeType; 38 typedef typename Alloc::iterator iterator; 39 typedef typename Alloc::const_iterator const_iterator; 40 41 public: 42 /// produce - produce a node, add it under control produce()43 NodeType* produce() { 44 NodeType* result = Alloc::allocate(); 45 Alloc::construct(result); 46 return result; 47 } 48 49 /// delegate - get the control of chunks owned by the client 50 // after calling delegate(), client will renouce its control 51 // of memory space. delegate(NodeFactory & pClient)52 void delegate(NodeFactory& pClient) { 53 if (this == &pClient) 54 return; 55 56 if (pClient.empty()) 57 return; 58 59 if (Alloc::empty()) { 60 replace(pClient); 61 pClient.renounce(); 62 return; 63 } 64 65 // neither me nor client is empty 66 concatenate(pClient); 67 pClient.renounce(); 68 } 69 70 private: 71 /// renounce - give up the control of all chunks renounce()72 void renounce() { Alloc::reset(); } 73 74 /// replace - be the agent of client. replace(NodeFactory & pClient)75 void replace(NodeFactory& pClient) { 76 Alloc::m_pRoot = pClient.Alloc::m_pRoot; 77 Alloc::m_pCurrent = pClient.Alloc::m_pCurrent; 78 Alloc::m_AllocatedNum = pClient.Alloc::m_AllocatedNum; 79 Alloc::m_NumAllocData = pClient.Alloc::m_NumAllocData; 80 } 81 82 /// concatenate - conncet two factories concatenate(NodeFactory & pClient)83 void concatenate(NodeFactory& pClient) { 84 Alloc::m_pCurrent->next = pClient.Alloc::m_pRoot; 85 Alloc::m_pCurrent = pClient.Alloc::m_pCurrent; 86 Alloc::m_AllocatedNum += pClient.Alloc::m_AllocatedNum; 87 Alloc::m_NumAllocData += pClient.Alloc::m_NumAllocData; 88 } 89 }; 90 91 } // namespace mcld 92 93 #endif // MCLD_ADT_TREEALLOCATOR_H_ 94