dune-fem  2.8-git
singleton.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_SINGLETON_HH
2 #define DUNE_FEM_SINGLETON_HH
3 
4 //- System includes
5 #include <cassert>
6 #include <algorithm>
7 #include <memory>
8 #include <typeindex>
9 #include <unordered_map>
10 #include <vector>
11 
12 //- dune-fem includes
14 
15 namespace Dune
16 {
17  namespace Fem
18  {
19  namespace detail
20  {
21  class SingletonStorage
22  {
23  protected:
24  // item to be stored in storage list
25  struct Item { virtual ~Item() {} };
26 
27  typedef std::shared_ptr< Item > WeakPointerType;
28  typedef std::unique_ptr< Item > PointerType;
29  typedef std::type_index KeyType;
30 
31  typedef std::pair< std::unordered_map< KeyType, std::shared_ptr< Item > >, std::vector<PointerType> > StorageType;
32 
33  // delete for singletons deleting each singleton object
34  // in reverse order of creation
35  struct SingletonDeleter
36  {
37  void operator()(StorageType* storage) const
38  {
39  // delete singletons in reverse order
40  std::for_each(storage->second.rbegin(), storage->second.rend(),
41  [](PointerType& item) { item.reset(); });
42 
43  storage->second.clear();
44  storage->first.clear();
45  }
46  };
47 
48  public:
49  typedef std::unique_ptr<StorageType, SingletonDeleter> StoragePointer;
50 
51  private:
52  static StoragePointer storage_;
53 
54  protected:
55  static StorageType& getStorage()
56  {
57  if(! storage_ )
58  {
59  storage_.reset( new StorageType() );
60  }
61 
62  return *storage_;
63  }
64  };
65  } // end namespace detail
66 
69  template< class Object >
70  class Singleton : public detail::SingletonStorage
71  {
72  typedef detail::SingletonStorage BaseType;
73  typedef typename BaseType::StorageType StorageType;
74  typedef typename BaseType::Item Item;
75  typedef typename BaseType::PointerType PointerType;
76  typedef typename BaseType::WeakPointerType WeakPointerType;
77 
78  using BaseType::getStorage;
79 
80  // item to be created containing the correct object
81  struct ItemWrapper : public Item
82  {
83  Object obj_;
84  template <class... Args>
85  ItemWrapper(Args &&... args) : obj_(std::forward< Args >( args )...)
86  {}
87  };
88  typedef ItemWrapper ItemWrapperType;
89 
90  // null delete for shared_ptr hash map
91  struct NullDeleter
92  {
93  void operator()(Item *p) const {}
94  };
95 
96  public:
100  template <class... Args>
101  static Object& instance(Args &&... args)
102  {
103  // capture reference as static variable to avoid map search later on
104  static Object& inst = getObject(std::forward< Args >( args )...);
105  return inst;
106  }
107 
108  protected:
109  // placing variables as static inside functions only works with gcc
110  static const bool placeStaticVariableInline = false ;
111 
114  template <class... Args>
115  static Object& getObject(Args &&... args)
116  {
117  // this way of creating static variables only works with gcc, not with clang
118  if constexpr ( placeStaticVariableInline )
119  {
120  static Object obj( std::forward< Args >( args )...);
121  return obj;
122  }
123  else
124  {
125  // get storage reference (see base class)
126  StorageType& storage = getStorage();
127 
128  // get pointer of singleton objects belonging to hash id
129  auto& ptr = storage.first[ std::type_index(typeid(Object)) ];
130  // if pointer has not been set, create object and set pointer
131  if( ! ptr )
132  {
134 
135  // create object in vector for later correct deletion order
136  storage.second.emplace_back( PointerType(new ItemWrapperType(std::forward< Args >( args )...) ) );
137 
138  // create pointer to object in hash map for later use
139  ptr = WeakPointerType( storage.second.back().operator->(), NullDeleter() );
140  }
141 
142  // return object reference
143  assert( dynamic_cast< ItemWrapperType* > (ptr.operator->()) );
144  return static_cast< ItemWrapperType& > (*ptr).obj_;
145  }
146  }
147 
148  };
149 
150  } // namespace Fem
151 
152 } // namespace Dune
153 
154 #endif // #ifndef DUNE_FEM_SINGLETONLIST_HH
Definition: bindguard.hh:11
static bool singleThreadMode()
returns true if program is operating on one thread currently
Definition: threadmanager.hh:74
return singleton instance of given Object type.
Definition: singleton.hh:71
static const bool placeStaticVariableInline
Definition: singleton.hh:110
static Object & getObject(Args &&... args)
return singleton instance of given Object type.
Definition: singleton.hh:115
static Object & instance(Args &&... args)
return singleton instance of given Object type.
Definition: singleton.hh:101