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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description:
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
37 #define NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
38 
39 #include <map>
40 
41 #include <boost/function.hpp>
42 #include <boost/call_traits.hpp>
43 #include <boost/concept_check.hpp>
44 #include <boost/thread/shared_mutex.hpp>
45 #include <boost/thread/locks.hpp>
46 
47 #include <boost/shared_ptr.hpp>
49 
50 using namespace std;
51 
52 namespace Nektar
53 {
54  namespace LibUtilities
55  {
56  typedef boost::unique_lock<boost::shared_mutex> WriteLock;
57  typedef boost::shared_lock<boost::shared_mutex> ReadLock;
58 
59  template <typename KeyType>
61  {
62  bool operator()(const KeyType &lhs, const KeyType &rhs) const
63  {
64  return lhs < rhs;
65  }
66  };
67 
68  template <typename KeyType, typename ValueT, typename opLessCreator = defOpLessCreator<KeyType> >
69  class NekManager
70  {
71  public:
72  BOOST_CLASS_REQUIRE(KeyType, boost, LessThanComparableConcept);
73 
74  typedef boost::shared_ptr<ValueT> ValueType;
75  typedef boost::function<ValueType (const KeyType& key)> CreateFuncType;
76  typedef std::map<KeyType, ValueType> ValueContainer;
77  typedef boost::shared_ptr<ValueContainer> ValueContainerShPtr;
78  typedef std::map<KeyType, CreateFuncType, opLessCreator> CreateFuncContainer;
79  typedef std::map<std::string, boost::shared_ptr<ValueContainer> > ValueContainerPool;
80  typedef boost::shared_ptr<bool> BoolSharedPtr;
81  typedef std::map<std::string, BoolSharedPtr> FlagContainerPool;
82 
83  NekManager(std::string whichPool="") :
84  m_values(),
85  m_globalCreateFunc(),
86  m_keySpecificCreateFuncs()
87 
88  {
89  if (!whichPool.empty())
90  {
91  typename ValueContainerPool::iterator iter = m_ValueContainerPool.find(whichPool);
92  if (iter != m_ValueContainerPool.end())
93  {
94  m_values = iter->second;
95  m_managementEnabled = m_managementEnabledContainerPool[whichPool];
96  }
97  else
98  {
99  m_values = ValueContainerShPtr(new ValueContainer);
100  m_ValueContainerPool[whichPool] = m_values;
101  if (m_managementEnabledContainerPool.find(whichPool) == m_managementEnabledContainerPool.end())
102  {
103  m_managementEnabledContainerPool[whichPool] = BoolSharedPtr(new bool(true));
104  }
105  m_managementEnabled = m_managementEnabledContainerPool[whichPool];
106  }
107  }
108  else
109  {
110  m_values = ValueContainerShPtr(new ValueContainer);
111  m_managementEnabled = BoolSharedPtr(new bool(true));
112  }
113  };
114 
115 
116  explicit NekManager(CreateFuncType f, std::string whichPool="") :
117  m_values(),
118  m_globalCreateFunc(f),
119  m_keySpecificCreateFuncs()
120  {
121  if (!whichPool.empty())
122  {
123  ReadLock v_rlock(m_mutex); // reading static members
124  typename ValueContainerPool::iterator iter = m_ValueContainerPool.find(whichPool);
125  if (iter != m_ValueContainerPool.end())
126  {
127  m_values = iter->second;
128  m_managementEnabled = m_managementEnabledContainerPool[whichPool];
129  }
130  else
131  {
132  v_rlock.unlock();
133  // now writing static members. Apparently upgrade_lock has less desirable properties
134  // than just dropping read lock, grabbing write lock.
135  // write will block until all reads are done, but reads cannot be acquired if write
136  // lock is blocking. In this context writes are supposed to be rare.
137  WriteLock v_wlock(m_mutex);
138  m_values = ValueContainerShPtr(new ValueContainer);
139  m_ValueContainerPool[whichPool] = m_values;
140  if (m_managementEnabledContainerPool.find(whichPool) == m_managementEnabledContainerPool.end())
141  {
142  m_managementEnabledContainerPool[whichPool] = BoolSharedPtr(new bool(true));
143  }
144  m_managementEnabled = m_managementEnabledContainerPool[whichPool];
145  }
146 
147  }
148  else
149  {
150  m_values = ValueContainerShPtr(new ValueContainer);
151  m_managementEnabled = BoolSharedPtr(new bool(true));
152  }
153  }
154 
156  {
157  }
158 
159  /// Register the given function and associate it with the key.
160  /// The return value is just to facilitate calling statically.
161  bool RegisterCreator(typename boost::call_traits<KeyType>::const_reference key,
162  const CreateFuncType& createFunc)
163  {
164  m_keySpecificCreateFuncs[key] = createFunc;
165 
166  return true;
167  }
168 
169  /// Register the Global Create Function.
170  /// The return value is just to facilitate calling statically.
171  bool RegisterGlobalCreator(const CreateFuncType& createFunc)
172  {
173  m_globalCreateFunc = createFunc;
174 
175  return true;
176  }
177 
178  bool AlreadyCreated(typename boost::call_traits<KeyType>::const_reference key)
179  {
180  bool value = false;
181  typename ValueContainer::iterator found = m_values->find(key);
182  if( found != m_values->end() )
183  {
184  value = true;
185  }
186 
187  return value;
188  }
189 
190  ValueType operator[](typename boost::call_traits<KeyType>::const_reference key)
191  {
192  typename ValueContainer::iterator found = m_values->find(key);
193 
194  if( found != m_values->end() )
195  {
196  return (*found).second;
197  }
198  else
199  {
200  // No object, create a new one.
201  CreateFuncType f = m_globalCreateFunc;
202  typename CreateFuncContainer::iterator keyFound = m_keySpecificCreateFuncs.find(key);
203  if( keyFound != m_keySpecificCreateFuncs.end() )
204  {
205  f = (*keyFound).second;
206  }
207 
208  if( f )
209  {
210  ValueType v = f(key);
211  if (*m_managementEnabled)
212  {
213  (*m_values)[key] = v;
214  }
215  return v;
216  }
217  else
218  {
219  std::string keyAsString = boost::lexical_cast<std::string>(key);
220  std::string message = std::string("No create func found for key ") + keyAsString;
221  NEKERROR(ErrorUtil::efatal, message.c_str());
222  static ValueType result;
223  return result;
224  }
225  }
226  }
227 
228  void DeleteObject(typename boost::call_traits<KeyType>::const_reference key)
229  {
230  typename ValueContainer::iterator found = m_values->find(key);
231 
232  if( found != m_values->end() )
233  {
234  m_values->erase(found);
235  }
236  }
237 
238  static void ClearManager(std::string whichPool = "")
239  {
240  typename ValueContainerPool::iterator x;
241  if (!whichPool.empty())
242  {
243  WriteLock v_wlock(m_mutex);
244 
245  x = m_ValueContainerPool.find(whichPool);
246  ASSERTL1(x != m_ValueContainerPool.end(),
247  "Could not find pool " + whichPool);
248  x->second->clear();
249  }
250  else
251  {
252  WriteLock v_wlock(m_mutex);
253 
254  for (x = m_ValueContainerPool.begin(); x != m_ValueContainerPool.end(); ++x)
255  {
256  x->second->clear();
257  }
258  }
259  }
260 
261  static void EnableManagement(std::string whichPool = "")
262  {
263  typename FlagContainerPool::iterator x;
264  if (!whichPool.empty())
265  {
266  WriteLock v_wlock(m_mutex);
267 
268  x = m_managementEnabledContainerPool.find(whichPool);
269  if (x != m_managementEnabledContainerPool.end())
270  {
271  (*x->second) = true;
272  }
273  else
274  {
275  m_managementEnabledContainerPool[whichPool] = BoolSharedPtr(new bool(true));
276  }
277  }
278  }
279 
280  static void DisableManagement(std::string whichPool = "")
281  {
282  typename FlagContainerPool::iterator x;
283  if (!whichPool.empty())
284  {
285  WriteLock v_wlock(m_mutex);
286 
287  x = m_managementEnabledContainerPool.find(whichPool);
288  if (x != m_managementEnabledContainerPool.end())
289  {
290  (*x->second) = false;
291  }
292  else
293  {
294  m_managementEnabledContainerPool[whichPool] = BoolSharedPtr(new bool(false));
295  }
296  }
297  }
298 
299  private:
302 
303  ValueContainerShPtr m_values;
304  BoolSharedPtr m_managementEnabled;
305  static ValueContainerPool m_ValueContainerPool;
306  static FlagContainerPool m_managementEnabledContainerPool;
307  CreateFuncType m_globalCreateFunc;
308  CreateFuncContainer m_keySpecificCreateFuncs;
309  static boost::shared_mutex m_mutex;
310  };
311  template <typename KeyType, typename ValueT, typename opLessCreator> typename NekManager<KeyType, ValueT, opLessCreator>::ValueContainerPool NekManager<KeyType, ValueT, opLessCreator>::m_ValueContainerPool;
313  template <typename KeyType, typename ValueT, typename opLessCreator>
314  typename boost::shared_mutex NekManager<KeyType, ValueT, opLessCreator>::m_mutex;
315  }
316 }
317 
318 
319 #endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
boost::unique_lock< boost::shared_mutex > WriteLock
Definition: NekFactory.hpp:70
static void DisableManagement(std::string whichPool="")
Definition: NekManager.hpp:280
boost::shared_ptr< ValueContainer > ValueContainerShPtr
Definition: NekManager.hpp:77
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:158
NekManager(CreateFuncType f, std::string whichPool="")
Definition: NekManager.hpp:116
static FlagContainerPool m_managementEnabledContainerPool
Definition: NekManager.hpp:306
NekManager(std::string whichPool="")
Definition: NekManager.hpp:83
static ValueContainerPool m_ValueContainerPool
Definition: NekManager.hpp:305
STL namespace.
boost::shared_ptr< bool > BoolSharedPtr
Definition: NekManager.hpp:80
StandardMatrixTag & lhs
static void EnableManagement(std::string whichPool="")
Definition: NekManager.hpp:261
std::map< KeyType, ValueType > ValueContainer
Definition: NekManager.hpp:76
bool RegisterCreator(typename boost::call_traits< KeyType >::const_reference 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:161
boost::function< ValueType(const KeyType &key)> CreateFuncType
Definition: NekManager.hpp:75
bool operator()(const KeyType &lhs, const KeyType &rhs) const
Definition: NekManager.hpp:62
std::map< std::string, boost::shared_ptr< ValueContainer > > ValueContainerPool
Definition: NekManager.hpp:79
void DeleteObject(typename boost::call_traits< KeyType >::const_reference key)
Definition: NekManager.hpp:228
boost::shared_lock< boost::shared_mutex > ReadLock
Definition: NekFactory.hpp:71
bool AlreadyCreated(typename boost::call_traits< KeyType >::const_reference key)
Definition: NekManager.hpp:178
std::map< KeyType, CreateFuncType, opLessCreator > CreateFuncContainer
Definition: NekManager.hpp:78
CreateFuncContainer m_keySpecificCreateFuncs
Definition: NekManager.hpp:308
static void ClearManager(std::string whichPool="")
Definition: NekManager.hpp:238
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
boost::shared_ptr< ValueT > ValueType
Definition: NekManager.hpp:74
static boost::shared_mutex m_mutex
Definition: NekManager.hpp:309
bool RegisterGlobalCreator(const CreateFuncType &createFunc)
Register the Global Create Function. The return value is just to facilitate calling statically...
Definition: NekManager.hpp:171
ValueContainerShPtr m_values
Definition: NekManager.hpp:303
std::map< std::string, BoolSharedPtr > FlagContainerPool
Definition: NekManager.hpp:81
ValueType operator[](typename boost::call_traits< KeyType >::const_reference key)
Definition: NekManager.hpp:190
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:191