ThreadedLoopMacros.hpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of OpenFLUID software
4  Copyright(c) 2007, INRA - Montpellier SupAgro
5 
6 
7  == GNU General Public License Usage ==
8 
9  OpenFLUID is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OpenFLUID is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21 
22 
23  == Other Usage ==
24 
25  Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26  license, and requires a written agreement between You and INRA.
27  Licensees for Other Usage of OpenFLUID may use this file in accordance
28  with the terms contained in the written agreement between You and INRA.
29 
30 */
31 
32 
33 /**
34  @file ThreadedLoopMacros.hpp
35 
36  @author Jean-Christophe FABRE <jean-christophe.fabre@inra.fr>
37  */
38 
39 
40 #ifndef __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__
41 #define __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__
42 
43 
44 #include <functional>
45 #include <thread>
46 #include <vector>
47 #include <system_error>
48 
50 
51 
52 // =====================================================================
53 // =====================================================================
54 
55 
56 #define _THREADGROUPID(_id) _M_##_id##_ThreadGroup
57 #define _THREADID(_id) _M_##_id##_Thread
58 
59 
60 // =====================================================================
61 // =====================================================================
62 
63 
64 #define _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(id,unitsclass,funcptr,...) \
65  openfluid::core::UnitsList_t* _UNITSLISTID(id) = mp_SpatialData->spatialUnits(unitsclass)->list(); \
66  if (_UNITSLISTID(id) != nullptr) \
67  { \
68  openfluid::core::UnitsList_t::iterator _UNITSLISTITERID(id) = _UNITSLISTID(id)->begin(); \
69  if (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
70  { \
71  openfluid::core::PcsOrd_t _PCSORDID(id) = _UNITSLISTITERID(id)->getProcessOrder(); \
72  while (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
73  { \
74  std::vector<std::thread> _THREADGROUPID(id); \
75  while (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end() && \
76  _UNITSLISTITERID(id)->getProcessOrder() == _PCSORDID(id)) \
77  { \
78  try \
79  { \
80  _THREADGROUPID(id).push_back(std::thread(std::bind(&funcptr,this,\
81  &(*_UNITSLISTITERID(id)),## __VA_ARGS__))); \
82  if (_THREADGROUPID(id).size() == (unsigned int)OPENFLUID_GetSimulatorMaxThreads()) \
83  { \
84  for (auto& _THREADID(id) : _THREADGROUPID(id)) \
85  _THREADID(id).join(); \
86  _THREADGROUPID(id).clear(); \
87  } \
88  } \
89  catch (std::system_error& E) \
90  { \
91  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, \
92  "Error in threaded loop (" + std::string(E.what()) +")"); \
93  } \
94  ++_UNITSLISTITERID(id); \
95  } \
96  for (auto& _THREADID(id) : _THREADGROUPID(id)) \
97  _THREADID(id).join(); \
98  _THREADGROUPID(id).clear(); \
99  if (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
100  _PCSORDID(id) = _UNITSLISTITERID(id)->getProcessOrder(); \
101  } \
102  } \
103  }
104 
105 /**
106  Macro for applying a threaded simulator to each unit of a class, following their process order
107  @param[in] unitsclass name of the units class
108  @param[in] funcptr member simulator name
109  @param[in] ... extra parameters to pass to the member simulator
110 */
111 #define APPLY_UNITS_ORDERED_LOOP_THREADED(unitsclass,funcptr,...) \
112  _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,unitsclass,funcptr,## __VA_ARGS__)
113 
114 
115 // =====================================================================
116 // =====================================================================
117 
118 
119 #define _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(id,funcptr,...) \
120  openfluid::core::UnitsPtrList_t* _UNITSPTRLISTID(id) = mp_SpatialData->allSpatialUnits(); \
121  if (_UNITSPTRLISTID(id) != nullptr) \
122  { \
123  openfluid::core::UnitsPtrList_t::iterator _UNITSPTRLISTITERID(id) = _UNITSPTRLISTID(id)->begin(); \
124  if (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) \
125  { \
126  openfluid::core::PcsOrd_t _PCSORDID(id) = (*_UNITSPTRLISTITERID(id))->getProcessOrder(); \
127  while (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) \
128  { \
129  std::vector<std::thread> _THREADGROUPID(id); \
130  while (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end() && \
131  (*_UNITSPTRLISTITERID(id))->getProcessOrder() == _PCSORDID(id)) \
132  { \
133  try \
134  { \
135  _THREADGROUPID(id).push_back(std::thread(std::bind(&funcptr,this,\
136  (*_UNITSPTRLISTITERID(id)),## __VA_ARGS__))); \
137  if (_THREADGROUPID(id).size() == (unsigned int)OPENFLUID_GetSimulatorMaxThreads()) \
138  { \
139  for (auto& _THREADID(id) : _THREADGROUPID(id)) \
140  _THREADID(id).join(); \
141  _THREADGROUPID(id).clear(); \
142  } \
143  }\
144  catch (std::system_error& E) \
145  { \
146  throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, \
147  "Error in threaded loop (" + std::string(E.what()) +")"); \
148  } \
149  ++_UNITSPTRLISTITERID(id); \
150  } \
151  for (auto& _THREADID(id) : _THREADGROUPID(id)) \
152  _THREADID(id).join(); \
153  _THREADGROUPID(id).clear(); \
154  if (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end())\
155  _PCSORDID(id) = (*_UNITSPTRLISTITERID(id))->getProcessOrder(); \
156  } \
157  } \
158  }
159 
160 /**
161  Macro for applying a threaded simulator to each unit of the domain, following their process order
162  @param[in] funcptr member simulator name
163  @param[in] ... extra parameters to pass to the member simulator
164 */
165 #define APPLY_ALLUNITS_ORDERED_LOOP_THREADED(funcptr,...) \
166  _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,funcptr,## __VA_ARGS__)
167 
168 
169 // =====================================================================
170 // =====================================================================
171 
172 
173 #endif /* __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__ */