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
14#include <map>
15#include <utility>
16
17namespace mcld {
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
25    : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > {
26 protected:
27  typedef GCFactoryBase<LinearAllocator<DataType, ChunkSize> > Alloc;
28  typedef std::map<KeyType, DataType*> KeyMap;
29
30 protected:
31  UniqueGCFactoryBase()
32      : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() {}
33
34  explicit UniqueGCFactoryBase(size_t pNum)
35      : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >(pNum) {}
36
37 public:
38  virtual ~UniqueGCFactoryBase() { f_KeyMap.clear(); }
39
40  DataType* find(const KeyType& pKey) {
41    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
42    if (dataIter != f_KeyMap.end())
43      return dataIter->second;
44    return 0;
45  }
46
47  const DataType* find(const KeyType& pKey) const {
48    typename KeyMap::const_iterator dataIter = f_KeyMap.find(pKey);
49    if (dataIter != f_KeyMap.end())
50      return dataIter->second;
51    return 0;
52  }
53
54  DataType* produce(const KeyType& pKey, bool& pExist) {
55    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
56    if (dataIter != f_KeyMap.end()) {
57      pExist = true;
58      return dataIter->second;
59    }
60    DataType* data = Alloc::allocate();
61    construct(data);
62    f_KeyMap.insert(std::make_pair(pKey, data));
63    pExist = false;
64    return data;
65  }
66
67  DataType* produce(const KeyType& pKey, const DataType& pValue, bool& pExist) {
68    typename KeyMap::iterator dataIter = f_KeyMap.find(pKey);
69    if (dataIter != f_KeyMap.end()) {
70      pExist = true;
71      return dataIter->second;
72    }
73    DataType* data = Alloc::allocate();
74    construct(data, pValue);
75    f_KeyMap.insert(std::make_pair(pKey, data));
76    pExist = false;
77    return data;
78  }
79
80 protected:
81  KeyMap f_KeyMap;
82};
83
84}  // namespace mcld
85
86#endif  // MCLD_SUPPORT_UNIQUEGCFACTORY_H_
87