1//===- UniqueGCFactory.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_SUPPORT_UNIQUEGCFACTORY_H
10#define MCLD_SUPPORT_UNIQUEGCFACTORY_H
11
12#include "mcld/Support/GCFactory.h"
13#include <map>
14#include <utility>
15
16namespace mcld
17{
18
19/** \class UniqueGCFactoryBase
20 *  \brief UniqueGCFactories are unique associative factories, meaning that
21 *  no two elements have the same key.
22 */
23template<typename KeyType, typename DataType, size_t ChunkSize>
24class UniqueGCFactoryBase : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> >
25{
26protected:
27  typedef GCFactoryBase<LinearAllocator<DataType, ChunkSize> > Alloc;
28  typedef std::map<KeyType, DataType*> KeyMap;
29
30protected:
31  UniqueGCFactoryBase()
32  : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >()
33  { }
34
35  UniqueGCFactoryBase(size_t pNum)
36  : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >(pNum)
37  { }
38
39public:
40  virtual ~UniqueGCFactoryBase()
41  { f_KeyMap.clear(); }
42
43  DataType* find(const KeyType& pKey) {
44    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
45    if (dataIter != f_KeyMap.end())
46      return dataIter->second;
47    return 0;
48  }
49
50  const DataType* find(const KeyType& pKey) const {
51    typename KeyMap::const_iterator dataIter = f_KeyMap.find(pKey);
52    if (dataIter != f_KeyMap.end())
53      return dataIter->second;
54    return 0;
55  }
56
57  DataType* produce(const KeyType& pKey, bool& pExist) {
58    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
59    if (dataIter != f_KeyMap.end()) {
60      pExist = true;
61      return dataIter->second;
62    }
63    DataType* data = Alloc::allocate();
64    construct(data);
65    f_KeyMap.insert(std::make_pair(pKey, data));
66    pExist = false;
67    return data;
68  }
69
70  DataType* produce(const KeyType& pKey, const DataType& pValue, bool& pExist) {
71    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
72    if (dataIter != f_KeyMap.end()) {
73      pExist = true;
74      return dataIter->second;
75    }
76    DataType* data = Alloc::allocate();
77    construct(data, pValue);
78    f_KeyMap.insert(std::make_pair(pKey, data));
79    pExist = false;
80    return data;
81  }
82
83protected:
84  KeyMap f_KeyMap;
85
86};
87
88} // namespace of mcld
89
90#endif
91
92