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 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 { 34 private: 35 typedef GCFactory<Node<DataType>, 64> Alloc; 36 37 public: 38 typedef Node<DataType> NodeType; 39 typedef typename Alloc::iterator iterator; 40 typedef typename Alloc::const_iterator const_iterator; 41 42 public: 43 /// produce - produce a node, add it under control produce()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. delegate(NodeFactory & pClient)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 71 private: 72 /// renounce - give up the control of all chunks renounce()73 void renounce() 74 { Alloc::reset(); } 75 76 /// replace - be the agent of client. replace(NodeFactory & pClient)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 concatenate(NodeFactory & pClient)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