• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
produce()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.
delegate(NodeFactory & pClient)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
renounce()75   void renounce()
76   { Alloc::reset(); }
77 
78   /// replace - be the agent of client.
replace(NodeFactory & pClient)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
concatenate(NodeFactory & pClient)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