TreeAllocator.h revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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
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{
34private:
35  typedef GCFactory<Node<DataType>, 64> Alloc;
36
37public:
38  typedef Node<DataType>                 NodeType;
39  typedef typename Alloc::iterator       iterator;
40  typedef typename Alloc::const_iterator const_iterator;
41
42public:
43  /// produce - produce a node, add it under control
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.
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
71private:
72  /// renounce - give up the control of all chunks
73  void renounce()
74  { Alloc::reset(); }
75
76  /// replace - be the agent of client.
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
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