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  static void EnableManagement(std::string whichPool = "")
285  {
286  if (!whichPool.empty())
287  {
288 #ifdef NEKTAR_USE_THREAD_SAFETY
289  WriteLock v_wlock(m_mutex);
290 #endif
291 
292  auto x = m_managementEnabledContainerPool.find(whichPool);
293  if (x != m_managementEnabledContainerPool.end())
294  {
295  (*x->second) = true;
296  }
297  else
298  {
300  BoolSharedPtr(new bool(true));
301  }
302  }
303  }
304 
305  static void DisableManagement(std::string whichPool = "")
306  {
307  if (!whichPool.empty())
308  {
309 #ifdef NEKTAR_USE_THREAD_SAFETY
310  WriteLock v_wlock(m_mutex);
311 #endif
312  auto x = m_managementEnabledContainerPool.find(whichPool);
313  if (x != m_managementEnabledContainerPool.end())
314  {
315  (*x->second) = false;
316  }
317  else
318  {
320  BoolSharedPtr(new bool(false));
321  }
322  }
323  }
324 
325 private:
329 
336 #ifdef NEKTAR_USE_THREAD_SAFETY
337  static boost::shared_mutex m_mutex;
338 #endif
339 };
340 template <typename KeyType, typename ValueT, typename opLessCreator>
343 template <typename KeyType, typename ValueT, typename opLessCreator>
345  NekManager<KeyType, ValueT,
346  opLessCreator>::m_managementEnabledContainerPool;
347 #ifdef NEKTAR_USE_THREAD_SAFETY
348 template <typename KeyType, typename ValueT, typename opLessCreator>
349 typename boost::shared_mutex
351 #endif
352 } // namespace LibUtilities
353 } // namespace Nektar
354 
355 #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:305
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
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:330
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:332
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:333
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:335
static void EnableManagement(std::string whichPool="")
Definition: NekManager.hpp:284
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:321
boost::unique_lock< boost::shared_mutex > WriteLock
Definition: Thread.h:320
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
bool operator()(const KeyType &lhs, const KeyType &rhs) const
Definition: NekManager.hpp:61