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_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 #include "mcld/ADT/TreeBase.h"
     17 
     18 namespace mcld
     19 {
     20 
     21 /** \class NodeFactory
     22  *  \brief NodeFactory manages the creation and destruction of mcld::Node.
     23  *
     24  *  NodeFactory guarantees all allocated memory are released finally. When
     25  *  the destructor of NodeFactory is called, all allocated memory are freed.
     26  *
     27  *  NodeFactory provides delegation of memory. Sometimes, we have to merge two
     28  *  NodeFactories, and NodeFactory::delegate() can move the memory from one
     29  *  NodeFactories to another.
     30  *
     31  *  @see LinearAllocator
     32  */
     33 template<typename DataType>
     34 class NodeFactory : public GCFactory<Node<DataType>, 64>
     35 {
     36 private:
     37   typedef GCFactory<Node<DataType>, 64> Alloc;
     38 
     39 public:
     40   typedef Node<DataType>                 NodeType;
     41   typedef typename Alloc::iterator       iterator;
     42   typedef typename Alloc::const_iterator const_iterator;
     43 
     44 public:
     45   /// produce - produce a node, add it under control
     46   NodeType* produce() {
     47     NodeType* result = Alloc::allocate();
     48     Alloc::construct(result);
     49     return result;
     50   }
     51 
     52   /// delegate - get the control of chunks owned by the client
     53   //  after calling delegate(), client will renouce its control
     54   //  of memory space.
     55   void delegate(NodeFactory& pClient) {
     56     if (this == &pClient)
     57       return;
     58 
     59     if (pClient.empty())
     60       return;
     61 
     62     if (Alloc::empty()) {
     63       replace(pClient);
     64       pClient.renounce();
     65       return;
     66     }
     67 
     68     // neither me nor client is empty
     69     concatenate(pClient);
     70     pClient.renounce();
     71   }
     72 
     73 private:
     74   /// renounce - give up the control of all chunks
     75   void renounce()
     76   { Alloc::reset(); }
     77 
     78   /// replace - be the agent of client.
     79   void replace(NodeFactory& pClient) {
     80     Alloc::m_pRoot = pClient.Alloc::m_pRoot;
     81     Alloc::m_pCurrent = pClient.Alloc::m_pCurrent;
     82     Alloc::m_AllocatedNum = pClient.Alloc::m_AllocatedNum;
     83     Alloc::m_NumAllocData = pClient.Alloc::m_NumAllocData;
     84   }
     85 
     86   /// concatenate - conncet two factories
     87   void concatenate(NodeFactory& pClient) {
     88     Alloc::m_pCurrent->next = pClient.Alloc::m_pRoot;
     89     Alloc::m_pCurrent = pClient.Alloc::m_pCurrent;
     90     Alloc::m_AllocatedNum += pClient.Alloc::m_AllocatedNum;
     91     Alloc::m_NumAllocData += pClient.Alloc::m_NumAllocData;
     92   }
     93 };
     94 
     95 } // namespace of mcld
     96 
     97 #endif
     98