TreeAllocator.h revision 37b74a387bb3993387029859c2d9d051c41c724e
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
12#include "mcld/ADT/TreeBase.h"
13#include "mcld/Support/GCFactory.h"
14
15#include <set>
16
17namespace 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 */
31template <typename DataType>
32class NodeFactory : public GCFactory<Node<DataType>, 64> {
33 private:
34  typedef GCFactory<Node<DataType>, 64> Alloc;
35
36 public:
37  typedef Node<DataType> NodeType;
38  typedef typename Alloc::iterator iterator;
39  typedef typename Alloc::const_iterator const_iterator;
40
41 public:
42  /// produce - produce a node, add it under control
43  NodeType* produce() {
44    NodeType* result = Alloc::allocate();
45    Alloc::construct(result);
46    return result;
47  }
48
49  /// delegate - get the control of chunks owned by the client
50  //  after calling delegate(), client will renouce its control
51  //  of memory space.
52  void delegate(NodeFactory& pClient) {
53    if (this == &pClient)
54      return;
55
56    if (pClient.empty())
57      return;
58
59    if (Alloc::empty()) {
60      replace(pClient);
61      pClient.renounce();
62      return;
63    }
64
65    // neither me nor client is empty
66    concatenate(pClient);
67    pClient.renounce();
68  }
69
70 private:
71  /// renounce - give up the control of all chunks
72  void renounce() { Alloc::reset(); }
73
74  /// replace - be the agent of client.
75  void replace(NodeFactory& pClient) {
76    Alloc::m_pRoot = pClient.Alloc::m_pRoot;
77    Alloc::m_pCurrent = pClient.Alloc::m_pCurrent;
78    Alloc::m_AllocatedNum = pClient.Alloc::m_AllocatedNum;
79    Alloc::m_NumAllocData = pClient.Alloc::m_NumAllocData;
80  }
81
82  /// concatenate - conncet two factories
83  void concatenate(NodeFactory& pClient) {
84    Alloc::m_pCurrent->next = pClient.Alloc::m_pRoot;
85    Alloc::m_pCurrent = pClient.Alloc::m_pCurrent;
86    Alloc::m_AllocatedNum += pClient.Alloc::m_AllocatedNum;
87    Alloc::m_NumAllocData += pClient.Alloc::m_NumAllocData;
88  }
89};
90
91}  // namespace mcld
92
93#endif  // MCLD_ADT_TREEALLOCATOR_H_
94