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 <mutex>
45#include <shared_mutex>
46#include <thread>
47#endif
48
50
52{
53#ifdef NEKTAR_USE_THREAD_SAFETY
54typedef std::unique_lock<std::shared_mutex> WriteLock;
55typedef std::shared_lock<std::shared_mutex> ReadLock;
56#endif
57
58template <typename KeyType> struct defOpLessCreator
59{
60 bool operator()(const KeyType &lhs, const KeyType &rhs) const
61 {
62 return lhs < rhs;
63 }
64};
65
66template <typename KeyType, typename ValueT,
67 typename opLessCreator = defOpLessCreator<KeyType>>
69{
70public:
71 typedef std::shared_ptr<ValueT> ValueType;
72 typedef std::function<ValueType(const KeyType &key)> CreateFuncType;
73 typedef std::map<KeyType, ValueType> ValueContainer;
74 typedef std::shared_ptr<ValueContainer> ValueContainerShPtr;
75 typedef std::map<KeyType, CreateFuncType, opLessCreator>
77 typedef std::map<std::string, std::shared_ptr<ValueContainer>>
79 typedef std::shared_ptr<bool> BoolSharedPtr;
80 typedef std::map<std::string, BoolSharedPtr> FlagContainerPool;
81
82 NekManager(std::string whichPool = "")
84 {
85 if (!whichPool.empty())
86 {
87 auto iter = m_ValueContainerPool.find(whichPool);
88 if (iter != m_ValueContainerPool.end())
89 {
90 m_values = iter->second;
93 }
94 else
95 {
97 m_ValueContainerPool[whichPool] = m_values;
98 if (m_managementEnabledContainerPool.find(whichPool) ==
100 {
102 BoolSharedPtr(new bool(true));
103 }
106 }
107 }
108 else
109 {
111 m_managementEnabled = BoolSharedPtr(new bool(true));
112 }
113 };
114
115 explicit NekManager(CreateFuncType f, std::string whichPool = "")
117 {
118 if (!whichPool.empty())
119 {
120#ifdef NEKTAR_USE_THREAD_SAFETY
121 ReadLock v_rlock(m_mutex); // reading static members
122#endif
123 auto iter = m_ValueContainerPool.find(whichPool);
124 if (iter != m_ValueContainerPool.end())
125 {
126 m_values = iter->second;
129 }
130 else
131 {
132#ifdef NEKTAR_USE_THREAD_SAFETY
133 v_rlock.unlock();
134 // Now writing static members. Apparently
135 // upgrade_lock has less desirable properties than
136 // just dropping read lock, grabbing write lock.
137 // write will block until all reads are done, but
138 // reads cannot be acquired if write lock is
139 // blocking. In this context writes are supposed to
140 // be rare.
141 WriteLock v_wlock(m_mutex);
142#endif
144 m_ValueContainerPool[whichPool] = m_values;
145 if (m_managementEnabledContainerPool.find(whichPool) ==
147 {
149 BoolSharedPtr(new bool(true));
150 }
153 }
154 }
155 else
156 {
158 m_managementEnabled = BoolSharedPtr(new bool(true));
159 }
160 }
161
163 {
164 }
165
166 /// Register the given function and associate it with the key.
167 /// The return value is just to facilitate calling statically.
168 bool RegisterCreator(const KeyType &key, const CreateFuncType &createFunc)
169 {
170 m_keySpecificCreateFuncs[key] = createFunc;
171
172 return true;
173 }
174
175 /// Register the Global Create Function.
176 /// The return value is just to facilitate calling statically.
177 bool RegisterGlobalCreator(const CreateFuncType &createFunc)
178 {
179 m_globalCreateFunc = createFunc;
180
181 return true;
182 }
183
184 ValueType operator[](const KeyType &key)
185 {
186 auto found = m_values->find(key);
187
188 if (found != m_values->end())
189 {
190 return (*found).second;
191 }
192 else
193 {
194 // No object, create a new one.
195 auto keyFound = m_keySpecificCreateFuncs.find(key);
196 bool isfound = keyFound != m_keySpecificCreateFuncs.end();
198 isfound ? (*keyFound).second : m_globalCreateFunc;
199
200 if (f)
201 {
202 ValueType v = f(key);
204 {
205 (*m_values)[key] = v;
206 }
207 return v;
208 }
209 else
210 {
211 std::stringstream ss;
212 ss << key;
213 std::string message =
214 "No create func found for key " + ss.str();
215 NEKERROR(ErrorUtil::efatal, message.c_str());
216 static ValueType result;
217 return result;
218 }
219 }
220 }
221
222 void DeleteObject(const KeyType &key)
223 {
224 auto found = m_values->find(key);
225
226 if (found != m_values->end())
227 {
228 m_values->erase(found);
229 }
230 }
231
232 static void ClearManager(std::string whichPool = "")
233 {
234#ifdef NEKTAR_USE_THREAD_SAFETY
235 WriteLock v_wlock(m_mutex);
236#endif
237
238 if (!whichPool.empty())
239 {
240 auto x = m_ValueContainerPool.find(whichPool);
242 "Could not find pool " + whichPool);
243 x->second->clear();
244 }
245 else
246 {
247 for (auto &x : m_ValueContainerPool)
248 {
249 x.second->clear();
250 }
251 }
252 }
253
254 static bool PoolCreated(std::string whichPool)
255 {
256 return m_ValueContainerPool.find(whichPool) !=
258 }
259
260 size_t PoolCount(std::string whichPool)
261 {
262 auto x = m_ValueContainerPool.find(whichPool);
264 "Could not find pool " + whichPool);
265 return x->second->size();
266 }
267
268 static void EnableManagement(std::string whichPool = "")
269 {
270 if (!whichPool.empty())
271 {
272#ifdef NEKTAR_USE_THREAD_SAFETY
273 WriteLock v_wlock(m_mutex);
274#endif
275
276 auto x = m_managementEnabledContainerPool.find(whichPool);
278 {
279 (*x->second) = true;
280 }
281 else
282 {
284 BoolSharedPtr(new bool(true));
285 }
286 }
287 }
288
289 static void DisableManagement(std::string whichPool = "")
290 {
291 if (!whichPool.empty())
292 {
293#ifdef NEKTAR_USE_THREAD_SAFETY
294 WriteLock v_wlock(m_mutex);
295#endif
296 auto x = m_managementEnabledContainerPool.find(whichPool);
298 {
299 (*x->second) = false;
300 }
301 else
302 {
304 BoolSharedPtr(new bool(false));
305 }
306 }
307 }
308
309private:
313
320#ifdef NEKTAR_USE_THREAD_SAFETY
321 static std::shared_mutex m_mutex;
322#endif
323};
324
325template <typename KeyType, typename ValueT, typename opLessCreator>
328template <typename KeyType, typename ValueT, typename opLessCreator>
330 NekManager<KeyType, ValueT,
331 opLessCreator>::m_managementEnabledContainerPool;
332#ifdef NEKTAR_USE_THREAD_SAFETY
333template <typename KeyType, typename ValueT, typename opLessCreator>
335#endif
336} // namespace Nektar::LibUtilities
337
338#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:202
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
static void DisableManagement(std::string whichPool="")
Definition: NekManager.hpp:289
std::shared_ptr< bool > BoolSharedPtr
Definition: NekManager.hpp:79
ValueType operator[](const KeyType &key)
Definition: NekManager.hpp:184
std::map< std::string, BoolSharedPtr > FlagContainerPool
Definition: NekManager.hpp:80
size_t PoolCount(std::string whichPool)
Definition: NekManager.hpp:260
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:168
NekManager(std::string whichPool="")
Definition: NekManager.hpp:82
std::function< ValueType(const KeyType &key)> CreateFuncType
Definition: NekManager.hpp:72
NekManager< KeyType, ValueType, opLessCreator > & operator=(const NekManager< KeyType, ValueType, opLessCreator > &rhs)
std::shared_ptr< ValueT > ValueType
Definition: NekManager.hpp:71
ValueContainerShPtr m_values
Definition: NekManager.hpp:314
std::map< std::string, std::shared_ptr< ValueContainer > > ValueContainerPool
Definition: NekManager.hpp:78
NekManager(CreateFuncType f, std::string whichPool="")
Definition: NekManager.hpp:115
static ValueContainerPool m_ValueContainerPool
Definition: NekManager.hpp:316
std::shared_ptr< ValueContainer > ValueContainerShPtr
Definition: NekManager.hpp:74
static bool PoolCreated(std::string whichPool)
Definition: NekManager.hpp:254
static FlagContainerPool m_managementEnabledContainerPool
Definition: NekManager.hpp:317
bool RegisterGlobalCreator(const CreateFuncType &createFunc)
Register the Global Create Function. The return value is just to facilitate calling statically.
Definition: NekManager.hpp:177
CreateFuncContainer m_keySpecificCreateFuncs
Definition: NekManager.hpp:319
static void EnableManagement(std::string whichPool="")
Definition: NekManager.hpp:268
void DeleteObject(const KeyType &key)
Definition: NekManager.hpp:222
std::map< KeyType, CreateFuncType, opLessCreator > CreateFuncContainer
Definition: NekManager.hpp:76
static void ClearManager(std::string whichPool="")
Definition: NekManager.hpp:232
NekManager(const NekManager< KeyType, ValueType, opLessCreator > &rhs)
std::map< KeyType, ValueType > ValueContainer
Definition: NekManager.hpp:73
std::shared_lock< std::shared_mutex > ReadLock
Definition: Thread.h:377
std::unique_lock< std::shared_mutex > WriteLock
Definition: Thread.h:376
bool operator()(const KeyType &lhs, const KeyType &rhs) const
Definition: NekManager.hpp:60