TreeAllocator.h revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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 18namespace 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 */ 33template<typename DataType> 34class NodeFactory : public GCFactory<Node<DataType>, 64> 35{ 36private: 37 typedef GCFactory<Node<DataType>, 64> Alloc; 38 39public: 40 typedef Node<DataType> NodeType; 41 typedef typename Alloc::iterator iterator; 42 typedef typename Alloc::const_iterator const_iterator; 43 44public: 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 73private: 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 99