Home | History | Annotate | Download | only in ADT
      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 
     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  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