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