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 #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
     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.
     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
     70   void renounce()
     71   { Alloc::reset(); }
     72 
     73   /// replace - be the agent of client.
     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
     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