Nektar++
NekManager.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: NekManager.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description:
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
36 #define NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
37 
38 #include <functional>
39 #include <map>
40 #include <memory>
41 #include <sstream>
42 
43 #ifdef NEKTAR_USE_THREAD_SAFETY
44 #include <boost/thread/locks.hpp>
45 #include <boost/thread/shared_mutex.hpp>
46 #endif
47 
49 
50 namespace Nektar
51 {
52 namespace LibUtilities
53 {
54 #ifdef NEKTAR_USE_THREAD_SAFETY
55 typedef boost::unique_lock<boost::shared_mutex> WriteLock;
56 typedef boost::shared_lock<boost::shared_mutex> ReadLock;
57 #endif
58 
59 template <typename KeyType> struct defOpLessCreator
60 {
61  bool operator()(const KeyType &lhs, const KeyType &rhs) const
62  {
63  return lhs < rhs;
64  }
65 };
66 
67 template <typename KeyType, typename ValueT,
68  typename opLessCreator = defOpLessCreator<KeyType>>
70 {
71 public:
72  typedef std::shared_ptr<ValueT> ValueType;
73  typedef std::function<ValueType(const KeyType &key)> CreateFuncType;
74  typedef std::map<KeyType, ValueType> ValueContainer;
75  typedef std::shared_ptr<ValueContainer> ValueContainerShPtr;
76  typedef std::map<KeyType, CreateFuncType, opLessCreator>
78  typedef std::map<std::string, std::shared_ptr<ValueContainer>>
80  typedef std::shared_ptr<bool> BoolSharedPtr;
81  typedef std::map<std::string, BoolSharedPtr> FlagContainerPool;
82 
83  NekManager(std::string whichPool = "")
85 
86  {
87  if (!whichPool.empty())
88  {
89  auto iter = m_ValueContainerPool.find(whichPool);
90  if (iter != m_ValueContainerPool.end())
91  {
92  m_values = iter->second;
95  }
96  else
97  {
99  m_ValueContainerPool[whichPool] = m_values;
100  if (m_managementEnabledContainerPool.find(whichPool) ==
102  {
104  BoolSharedPtr(new bool(true));
105  }
108  }
109  }
110  else
111  {
113  m_managementEnabled = BoolSharedPtr(new bool(true));
114  }
115  };
116 
117  explicit NekManager(CreateFuncType f, std::string whichPool = "")
119  {
120  if (!whichPool.empty())
121  {
122 #ifdef NEKTAR_USE_THREAD_SAFETY
123  ReadLock v_rlock(m_mutex); // reading static members
124 #endif
125  auto iter = m_ValueContainerPool.find(whichPool);
126  if (iter != m_ValueContainerPool.end())
127  {
128  m_values = iter->second;
131  }
132  else
133  {
134 #ifdef NEKTAR_USE_THREAD_SAFETY
135  v_rlock.unlock();
136  // now writing static members. Apparently
137  // upgrade_lock has less desirable properties than
138  // just dropping read lock, grabbing write lock.
139  // write will block until all reads are done, but
140  // reads cannot be acquired if write lock is
141  // blocking. In this context writes are supposed to
142  // be rare.
143  WriteLock v_wlock(m_mutex);
144 #endif
146  m_ValueContainerPool[whichPool] = m_values;
147  if (m_managementEnabledContainerPool.find(whichPool) ==
149  {
151  BoolSharedPtr(new bool(true));
152  }
155  }
156  }
157  else
158  {
160  m_managementEnabled = BoolSharedPtr(new bool(true));
161  }
162  }
163 
165  {
166  }
167 
168  /// Register the given function and associate it with the key.
169  /// The return value is just to facilitate calling statically.
170  bool RegisterCreator(const KeyType &key, const CreateFuncType &createFunc)
171  {
172  m_keySpecificCreateFuncs[key] = createFunc;
173 
174  return true;
175  }
176 
177  /// Register the Global Create Function.
178  /// The return value is just to facilitate calling statically.
179  bool RegisterGlobalCreator(const CreateFuncType &createFunc)
180  {
181  m_globalCreateFunc = createFunc;
182 
183  return true;
184  }
185 
186  bool AlreadyCreated(const KeyType &key)
187  {
188  bool value = false;
189  auto found = m_values->find(key);
190  if (found != m_values->end())
191  {
192  value = true;
193  }
194 
195  return value;
196  }
197 
198  ValueType operator[](const KeyType &key)
199  {
200  auto found = m_values->find(key);
201 
202  if (found != m_values->end())
203  {
204  return (*found).second;
205  }
206  else
207  {
208  // No object, create a new one.
210  auto keyFound = m_keySpecificCreateFuncs.find(key);
211  if (keyFound != m_keySpecificCreateFuncs.end())
212  {
213  f = (*keyFound).second;
214  }
215 
216  if (f)
217  {
218  ValueType v = f(key);
219  if (*m_managementEnabled)
220  {
221  (*m_values)[key] = v;
222  }
223  return v;
224  }
225  else
226  {
227  std::stringstream ss;
228  ss << key;
229  std::string message =
230  "No create func found for key " + ss.str();
231  NEKERROR(ErrorUtil::efatal, message.c_str());
232  static ValueType result;
233  return result;
234  }
235  }
236  }
237 
238  void DeleteObject(const KeyType &key)
239  {
240  auto found = m_values->find(key);
241 
242  if (found != m_values->end())
243  {
244  m_values->erase(found);
245  }
246  }
247 
248  static void ClearManager(std::string whichPool = "")
249  {
250  if (!whichPool.empty())
251  {
252 #ifdef NEKTAR_USE_THREAD_SAFETY
253  WriteLock v_wlock(m_mutex);
254 #endif
255  auto x = m_ValueContainerPool.find(whichPool);
256  ASSERTL1(x != m_ValueContainerPool.end(),
257  "Could not find pool " + whichPool);
258  x->second->clear();
259  }
260  else
261  {
262 #ifdef NEKTAR_USE_THREAD_SAFETY
263  WriteLock v_wlock(m_mutex);
264 #endif
265 
266  for (auto &x : m_ValueContainerPool)
267  {
268  x.second->clear();
269  }
270  }
271  }
272 
273  static bool PoolCreated(std::string whichPool)
274  {
275  bool value = false;
276  auto x = m_ValueContainerPool.find(whichPool);
277  if (x != m_ValueContainerPool.end())
278  {
279  value = true;
280  }
281  return value;
282  }
283 
284  size_t PoolCount(std::string whichPool)
285  {
286  auto x = m_ValueContainerPool.find(whichPool);
287  ASSERTL1(x != m_ValueContainerPool.end(),
288  "Could not find pool " + whichPool);
289  return x->second->size();
290  }
291 
292  static void EnableManagement(std::string whichPool = "")
293  {
294  if (!whichPool.empty())
295  {
296 #ifdef NEKTAR_USE_THREAD_SAFETY
297  WriteLock v_wlock(m_mutex);
298 #endif
299 
300  auto x = m_managementEnabledContainerPool.find(whichPool);
301  if (x != m_managementEnabledContainerPool.end())
302  {
303  (*x->second) = true;
304  }
305  else
306  {
308  BoolSharedPtr(new bool(true));
309  }
310  }
311  }
312 
313  static void DisableManagement(std::string whichPool = "")
314  {
315  if (!whichPool.empty())
316  {
317 #ifdef NEKTAR_USE_THREAD_SAFETY
318  WriteLock v_wlock(m_mutex);
319 #endif
320  auto x = m_managementEnabledContainerPool.find(whichPool);
321  if (x != m_managementEnabledContainerPool.end())
322  {
323  (*x->second) = false;
324  }
325  else
326  {
328  BoolSharedPtr(new bool(false));
329  }
330  }
331  }
332 
333 private:
337 
344 #ifdef NEKTAR_USE_THREAD_SAFETY
345  static boost::shared_mutex m_mutex;
346 #endif
347 };
348 template <typename KeyType, typename ValueT, typename opLessCreator>
351 template <typename KeyType, typename ValueT, typename opLessCreator>
353  NekManager<KeyType, ValueT,
354  opLessCreator>::m_managementEnabledContainerPool;
355 #ifdef NEKTAR_USE_THREAD_SAFETY
356 template <typename KeyType, typename ValueT, typename opLessCreator>
357 typename boost::shared_mutex
359 #endif
360 } // namespace LibUtilities
361 } // namespace Nektar
362 
363 #endif // NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
static void DisableManagement(std::string whichPool="")
Definition: NekManager.hpp:313
bool AlreadyCreated(const KeyType &key)
Definition: NekManager.hpp:186
std::shared_ptr< bool > BoolSharedPtr
Definition: NekManager.hpp:80
ValueType operator[](const KeyType &key)
Definition: NekManager.hpp:198
std::map< std::string, BoolSharedPtr > FlagContainerPool
Definition: NekManager.hpp:81
size_t PoolCount(std::string whichPool)
Definition: NekManager.hpp:284
bool RegisterCreator(const KeyType &key, const CreateFuncType &createFunc)
Register the given function and associate it with the key. The return value is just to facilitate cal...
Definition: NekManager.hpp:170
NekManager(std::string whichPool="")
Definition: NekManager.hpp:83
std::function< ValueType(const KeyType &key)> CreateFuncType
Definition: NekManager.hpp:73
NekManager< KeyType, ValueType, opLessCreator > & operator=(const NekManager< KeyType, ValueType, opLessCreator > &rhs)
std::shared_ptr< ValueT > ValueType
Definition: NekManager.hpp:72
ValueContainerShPtr m_values
Definition: NekManager.hpp:338
std::map< std::string, std::shared_ptr< ValueContainer > > ValueContainerPool
Definition: NekManager.hpp:79
NekManager(CreateFuncType f, std::string whichPool="")
Definition: NekManager.hpp:117
static ValueContainerPool m_ValueContainerPool
Definition: NekManager.hpp:340
std::shared_ptr< ValueContainer > ValueContainerShPtr
Definition: NekManager.hpp:75
static bool PoolCreated(std::string whichPool)
Definition: NekManager.hpp:273
static FlagContainerPool m_managementEnabledContainerPool
Definition: NekManager.hpp:341
bool RegisterGlobalCreator(const CreateFuncType &createFunc)
Register the Global Create Function. The return value is just to facilitate calling statically.
Definition: NekManager.hpp:179
CreateFuncContainer m_keySpecificCreateFuncs
Definition: NekManager.hpp:343
static void EnableManagement(std::string whichPool="")
Definition: NekManager.hpp:292
void DeleteObject(const KeyType &key)
Definition: NekManager.hpp:238
std::map< KeyType, CreateFuncType, opLessCreator > CreateFuncContainer
Definition: NekManager.hpp:77
static void ClearManager(std::string whichPool="")
Definition: NekManager.hpp:248
NekManager(const NekManager< KeyType, ValueType, opLessCreator > &rhs)
std::map< KeyType, ValueType > ValueContainer
Definition: NekManager.hpp:74
boost::shared_lock< boost::shared_mutex > ReadLock
Definition: Thread.h:380
boost::unique_lock< boost::shared_mutex > WriteLock
Definition: Thread.h:379
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
bool operator()(const KeyType &lhs, const KeyType &rhs) const
Definition: NekManager.hpp:61