runTimeSelectionTables.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  Macros to ease declaration of run-time selection tables.
29 
30  declareRunTimeSelectionTable is used to create a run-time selection table
31  for a base-class which holds constructor pointers on the table.
32 
33  declareRunTimeNewSelectionTable is used to create a run-time selection
34  table for a derived-class which holds "New" pointers on the table.
35 
36 \*---------------------------------------------------------------------------*/
37 
38 #include "token.H"
39 
40 #ifndef Foam_runTimeSelectionTables_H
41 #define Foam_runTimeSelectionTables_H
42 
43 #include <memory> // For std::unique_ptr
44 #include <utility> // For std::pair
45 
46 #include "autoPtr.H"
47 #include "HashTable.H"
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 // Common infrastructure
52 
53 // Not used directly: declare run-time selection (variables and methods)
54 #define declareRunTimeSelectionTableBase(returnType,prefix,argList) \
55  \
56  /* Function pointer type: construct from argList */ \
57  typedef returnType (*prefix##Ptr)argList; \
58  \
59  /* Function table type: construct from argList */ \
60  typedef ::Foam::HashTable \
61  < \
62  prefix##Ptr, \
63  ::Foam::word, \
64  ::Foam::Hash<::Foam::word> \
65  > prefix##TableType; \
66  \
67  /* Lookup aliases for constructors */ \
68  typedef ::Foam::HashTable \
69  < \
70  std::pair<::Foam::word,int>, \
71  ::Foam::word, \
72  ::Foam::Hash<::Foam::word> \
73  > prefix##CompatTableType; \
74  \
75  /* Table singleton (storage) */ \
76  static prefix##TableType* prefix##TablePtr_; \
77  \
78  /* Lookup aliases singleton (storage) */ \
79  static std::unique_ptr<prefix##CompatTableType> prefix##CompatTablePtr_; \
80  \
81  /* Aliases singleton (access) */ \
82  static prefix##CompatTableType& prefix##CompatTable(); \
83  \
84  /* Table construct/destruct helper */ \
85  static void prefix##TablePtr_construct(bool load); \
86  \
87  /* Lookup function pointer from singleton, nullptr if not found */ \
88  static prefix##Ptr prefix##Table(const ::Foam::word& k)
89 
90 
91 // Not used directly: storage and helper methods for runtime tables
92 // - uses automatic cleanup for compat table (issue #2314)
93 #define defineRunTimeSelectionTableBase(baseType,prefix,Tspecialize) \
94  \
95  /* Define table singleton (storage) */ \
96  Tspecialize prefix##TableType* prefix##TablePtr_(nullptr); \
97  \
98  /* Define aliases singleton (storage) */ \
99  Tspecialize \
100  std::unique_ptr<prefix##CompatTableType> prefix##CompatTablePtr_(nullptr); \
101  \
102  /* Define table singleton (access) for aliases */ \
103  Tspecialize prefix##CompatTableType& prefix##CompatTable() \
104  { \
105  if (!prefix##CompatTablePtr_) \
106  { \
107  prefix##CompatTablePtr_.reset(new prefix##CompatTableType(16)); \
108  } \
109  return *(prefix##CompatTablePtr_); \
110  } \
111  \
112  /* Table construct/destruct helper */ \
113  Tspecialize void prefix##TablePtr_construct(bool load) \
114  { \
115  static bool constructed = false; \
116  if (load) \
117  { \
118  if (!constructed) \
119  { \
120  prefix##TablePtr_ = new prefix##TableType; \
121  constructed = true; \
122  } \
123  } \
124  else if (prefix##TablePtr_) \
125  { \
126  delete prefix##TablePtr_; \
127  prefix##TablePtr_ = nullptr; \
128  } \
129  } \
130  \
131  /* Define lookup function pointer (singleton) */ \
132  Tspecialize prefix##Ptr prefix##Table(const ::Foam::word& k) \
133  { \
134  if (prefix##TablePtr_) \
135  { \
136  const auto& tbl = *prefix##TablePtr_; \
137  auto iter = tbl.cfind(k); \
138  if (!iter.good() && prefix##CompatTablePtr_) \
139  { \
140  const auto altIter = prefix##CompatTablePtr_->cfind(k); \
141  if (altIter.good()) \
142  { \
143  const auto& alt = altIter.val(); /* <word,int> */ \
144  iter = tbl.cfind(alt.first); \
145  if (::Foam::error::warnAboutAge(alt.second)) \
146  { \
147  std::cerr \
148  << "Using [v" << alt.second << "] '" << k \
149  << "' instead of '" << alt.first \
150  << "' in selection table: " \
151  << #baseType << '\n' << std::endl; \
152  ::Foam::error::warnAboutAge("lookup", alt.second); \
153  } \
154  } \
155  } \
156  if (iter.good()) \
157  { \
158  return iter.val(); \
159  } \
160  } \
161  return nullptr; \
162  }
163 
164 
165 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
166 
167 //
168 // Declaration Macros
169 //
171 //- Declare a run-time selection (variables and adder classes)
172 // The ptrWrapper is typically a Foam::autoPtr or a Foam::tmp container.
173 #define declareRunTimeSelectionTable\
174 (ptrWrapper,baseType,argNames,argList,parList) \
175  \
176  declareRunTimeSelectionTableBase( \
177  ptrWrapper<baseType>, argNames##Constructor, argList); \
178  \
179  /* Helper to add compatibility/alias for runtime selection table */ \
180  template<class baseType##Type> \
181  struct addAlias##argNames##ConstructorToTable \
182  { \
183  explicit addAlias##argNames##ConstructorToTable \
184  ( \
185  const ::Foam::word& k, \
186  const ::Foam::word& alias, \
187  const int ver \
188  ) \
189  { \
190  argNames##ConstructorCompatTable() \
191  .set(alias, std::pair<::Foam::word,int>(k,ver)); \
192  } \
193  }; \
194  \
195  /* Helper to add constructor from argList to table */ \
196  template<class baseType##Type> \
197  struct add##argNames##ConstructorToTable \
198  { \
199  static ptrWrapper<baseType> New argList \
200  { \
201  return ptrWrapper<baseType>(new baseType##Type parList); \
202  } \
203  \
204  explicit add##argNames##ConstructorToTable \
205  ( \
206  const ::Foam::word& k = baseType##Type::typeName \
207  ) \
208  { \
209  argNames##ConstructorTablePtr_construct(true); \
210  if (!argNames##ConstructorTablePtr_->insert(k, New)) \
211  { \
212  std::cerr \
213  << "Duplicate entry " << k << " in runtime table " \
214  << #baseType << std::endl; \
215  ::Foam::error::safePrintStack(std::cerr); \
216  } \
217  } \
218  \
219  ~add##argNames##ConstructorToTable() \
220  { \
221  argNames##ConstructorTablePtr_construct(false); \
222  } \
223  \
224  add##argNames##ConstructorToTable \
225  (const add##argNames##ConstructorToTable&) = delete; \
226  \
227  void operator= \
228  (const add##argNames##ConstructorToTable&) = delete; \
229  }; \
230  \
231  /* Helper to add constructor from argList to table */ \
232  /* Remove only the entry (not the table) upon destruction */ \
233  template<class baseType##Type> \
234  struct addRemovable##argNames##ConstructorToTable \
235  { \
236  const ::Foam::word name; /* Lookup name for later removal */ \
237  \
238  static ptrWrapper<baseType> New argList \
239  { \
240  return ptrWrapper<baseType>(new baseType##Type parList); \
241  } \
242  \
243  explicit addRemovable##argNames##ConstructorToTable \
244  ( \
245  const ::Foam::word& k = baseType##Type::typeName \
246  ) \
247  : \
248  name(k) \
249  { \
250  argNames##ConstructorTablePtr_construct(true); \
251  argNames##ConstructorTablePtr_->set(k, New); \
252  } \
253  \
254  ~addRemovable##argNames##ConstructorToTable() \
255  { \
256  if (argNames##ConstructorTablePtr_) \
257  { \
258  argNames##ConstructorTablePtr_->erase(name); \
259  } \
260  } \
261  \
262  addRemovable##argNames##ConstructorToTable \
263  (const addRemovable##argNames##ConstructorToTable&) = delete; \
264  \
265  void operator= \
266  (const addRemovable##argNames##ConstructorToTable&) = delete; \
267  };
268 
269 
270 //- Declare a run-time selection for derived classes
271 #define declareRunTimeNewSelectionTable\
272 (ptrWrapper,baseType,argNames,argList,parList) \
273  \
274  declareRunTimeSelectionTableBase( \
275  ptrWrapper<baseType>,argNames##Constructor,argList); \
276  \
277  /* Helper to add compatibility/alias for runtime selection table */ \
278  template<class baseType##Type> \
279  struct addAlias##argNames##ConstructorToTable \
280  { \
281  explicit addAlias##argNames##ConstructorToTable \
282  ( \
283  const ::Foam::word& k, \
284  const ::Foam::word& alias, \
285  const int ver \
286  ) \
287  { \
288  argNames##ConstructorCompatTable() \
289  .set(alias, std::pair<::Foam::word,int>(k,ver)); \
290  } \
291  }; \
292  \
293  /* Helper to add constructor from argList to table */ \
294  template<class baseType##Type> \
295  struct add##argNames##ConstructorToTable \
296  { \
297  static ptrWrapper<baseType> New##baseType argList \
298  { \
299  return ptrWrapper<baseType>(baseType##Type::New parList.ptr()); \
300  } \
301  \
302  explicit add##argNames##ConstructorToTable \
303  ( \
304  const ::Foam::word& k = baseType##Type::typeName \
305  ) \
306  { \
307  argNames##ConstructorTablePtr_construct(true); \
308  if (!argNames##ConstructorTablePtr_->insert(k, New##baseType)) \
309  { \
310  std::cerr \
311  << "Duplicate entry " << k << " in runtime table " \
312  << #baseType << std::endl; \
313  ::Foam::error::safePrintStack(std::cerr); \
314  } \
315  } \
316  \
317  ~add##argNames##ConstructorToTable() \
318  { \
319  argNames##ConstructorTablePtr_construct(false); \
320  } \
321  \
322  add##argNames##ConstructorToTable \
323  (const add##argNames##ConstructorToTable&) = delete; \
324  \
325  void operator= \
326  (const add##argNames##ConstructorToTable&) = delete; \
327  }; \
328  \
329  /* Helper to add constructor from argList to table */ \
330  template<class baseType##Type> \
331  struct addRemovable##argNames##ConstructorToTable \
332  { \
333  const ::Foam::word name; /* Retain name for later removal */ \
334  \
335  static ptrWrapper<baseType> New##baseType argList \
336  { \
337  return ptrWrapper<baseType>(baseType##Type::New parList.ptr()); \
338  } \
339  \
340  explicit addRemovable##argNames##ConstructorToTable \
341  ( \
342  const ::Foam::word& k = baseType##Type::typeName \
343  ) \
344  : \
345  name(k) \
346  { \
347  argNames##ConstructorTablePtr_construct(true); \
348  argNames##ConstructorTablePtr_->set(k, New##baseType); \
349  } \
350  \
351  ~addRemovable##argNames##ConstructorToTable() \
352  { \
353  if (argNames##ConstructorTablePtr_) \
354  { \
355  argNames##ConstructorTablePtr_->erase(name); \
356  } \
357  } \
358  \
359  addRemovable##argNames##ConstructorToTable \
360  (const addRemovable##argNames##ConstructorToTable&) = delete; \
361  \
362  void operator= \
363  (const addRemovable##argNames##ConstructorToTable&) = delete; \
364  };
365 
366 
367 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
368 
369 //
370 // Definition Macros
371 //
372 
373 //- Define run-time selection table
374 #define defineRunTimeSelectionTable(baseType,argNames) \
375  \
376  defineRunTimeSelectionTableBase( \
377  baseType,baseType::argNames##Constructor,)
378 
379 
380 //- Define run-time selection table for template classes
381 // use when baseType doesn't need a template argument (eg, is a typedef)
382 #define defineTemplateRunTimeSelectionTable(baseType,argNames) \
383  \
384  defineRunTimeSelectionTableBase( \
385  baseType,baseType::argNames##Constructor,template<>)
387 
388 //- Define run-time selection table for template classes
389 // use when baseType requires the Targ template argument
390 #define defineTemplatedRunTimeSelectionTable(baseType,argNames,Targ) \
391  \
392  defineRunTimeSelectionTableBase( \
393  baseType,baseType<Targ>::argNames##Constructor,template<>)
394 
395 
396 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
398 #endif
399 
400 // ************************************************************************* //