• 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 
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