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