Documentation for OpenFLUID 2.2.2
Loading...
Searching...
No Matches
ThreadedLoopMacros.hpp
Go to the documentation of this file.
1/*
2
3 This file is part of OpenFLUID software
4 Copyright(c) 2021-2026, INRAE
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 @cond OpenFLUID:completion
39 {
40 "contexts" : ["SIMULATOR", "OBSERVER"],
41 "menupath" : ["Fortran integration"],
42 "title" : "Include ThreadedLoopMacros header",
43 "text" : "#include <openfluid/ware/ThreadedLoopMacros.hpp>"
44 }
45 @endcond
46*/
47
48
49#ifndef __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__
50#define __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__
51
52
53#include <functional>
54#include <thread>
55#include <vector>
56#include <system_error>
57
59
60
61// =====================================================================
62// =====================================================================
63
64
65#define _THREADGROUPID(_id) _M_##_id##_ThreadGroup
66#define _THREADID(_id) _M_##_id##_Thread
67
68
69// =====================================================================
70// =====================================================================
71
72
73#define _RUN_UNIT_GROUP_THREADED(id,iter,end,unitptr,funcptr,cond,...) \
74 std::vector<std::thread> _THREADGROUPID(id); \
75 while ((iter) != (end) && (cond)) \
76 { \
77 try \
78 { \
79 _THREADGROUPID(id).push_back(std::thread(std::bind(&funcptr,this,unitptr,## __VA_ARGS__))); \
80 if (_THREADGROUPID(id).size() == (unsigned int)OPENFLUID_GetSimulatorMaxThreads()) \
81 { \
82 for (auto& _THREADID(id) : _THREADGROUPID(id)) \
83 _THREADID(id).join(); \
84 _THREADGROUPID(id).clear(); \
85 } \
86 } \
87 catch (std::system_error& E) \
88 { \
89 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, \
90 "Error in threaded loop (" + std::string(E.what()) + ")"); \
91 } \
92 ++(iter); \
93 } \
94 for (auto& _THREADID(id) : _THREADGROUPID(id)) \
95 _THREADID(id).join(); \
96
97
98// =====================================================================
99// =====================================================================
100
101
102#define _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(id,unitsclass,funcptr,...) \
103 openfluid::core::UnitsList_t* _UNITSLISTID(id) = mp_SpatialData->spatialUnits(unitsclass)->list(); \
104 if (_UNITSLISTID(id) != nullptr) \
105 { \
106 openfluid::core::UnitsList_t::iterator _UNITSLISTITERID(id) = _UNITSLISTID(id)->begin(); \
107 while (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
108 { \
109 openfluid::core::PcsOrd_t _PCSORDID(id) = _UNITSLISTITERID(id)->getProcessOrder(); \
110 _RUN_UNIT_GROUP_THREADED(id,_UNITSLISTITERID(id),_UNITSLISTID(id)->end(), &(*_UNITSLISTITERID(id)), funcptr, \
111 _UNITSLISTITERID(id)->getProcessOrder() == _PCSORDID(id), ## __VA_ARGS__); \
112 } \
113 }
114
115/**
116 Macro for applying a threaded simulator to each unit of a class, following their process order
117 @param[in] unitsclass name of the units class
118 @param[in] funcptr member simulator name
119 @param[in] ... extra parameters to pass to the member simulator
120
121 @cond OpenFLUID:completion
122 {
123 "contexts" : ["SIMULATOR", "OBSERVER"],
124 "menupath" : ["Loops"],
125 "title" : "Threaded ordered loop on spatial units of a class",
126 "text" : "APPLY_UNITS_ORDERED_LOOP_THREADED(\"%%SEL_START%%UnitsClass%%SEL_END%%\",FuncPtr)"
127 }
128 @endcond
129*/
130#define APPLY_UNITS_ORDERED_LOOP_THREADED(unitsclass,funcptr,...) \
131 _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,unitsclass,funcptr,## __VA_ARGS__)
132
133
134// =====================================================================
135// =====================================================================
136
137
138#define _APPLY_UNITS_UNORDERED_LOOP_THREADED_WITHID(id,unitsclass,funcptr,...) \
139 openfluid::core::UnitsList_t* _UNITSLISTID(id) = mp_SpatialData->spatialUnits(unitsclass)->list(); \
140 if (_UNITSLISTID(id) != nullptr) \
141 { \
142 openfluid::core::UnitsList_t::iterator _UNITSLISTITERID(id) = _UNITSLISTID(id)->begin(); \
143 _RUN_UNIT_GROUP_THREADED(id,_UNITSLISTITERID(id),_UNITSLISTID(id)->end(),&(*_UNITSLISTITERID(id)),funcptr, \
144 true,## __VA_ARGS__); \
145 }
146
147/**
148 Macro for applying a threaded simulator to each unit of a class, without considering process order
149 @param[in] unitsclass name of the units class
150 @param[in] funcptr member simulator name
151 @param[in] ... extra parameters to pass to the member simulator
152
153 @cond OpenFLUID:completion
154 {
155 "contexts" : ["SIMULATOR", "OBSERVER"],
156 "menupath" : ["Loops"],
157 "title" : "Threaded loop on spatial units of a class",
158 "text" : "APPLY_UNITS_LOOP_THREADED(\"%%SEL_START%%UnitsClass%%SEL_END%%\",FuncPtr)"
159 }
160 @endcond
161*/
162#define APPLY_UNITS_UNORDERED_LOOP_THREADED(unitsclass,funcptr,...) \
163 _APPLY_UNITS_UNORDERED_LOOP_THREADED_WITHID(__LINE__,unitsclass,funcptr,## __VA_ARGS__)
164
165
166// =====================================================================
167// =====================================================================
168
169
170/* TODO May factorize UnitsPtrList_t to UnitsList_t ? */
171#define _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(id,funcptr,...) \
172 openfluid::core::UnitsPtrList_t* _UNITSPTRLISTID(id) = mp_SpatialData->allSpatialUnits(); \
173 if (_UNITSPTRLISTID(id) != nullptr) \
174 { \
175 openfluid::core::UnitsPtrList_t::iterator _UNITSPTRLISTITERID(id) = _UNITSPTRLISTID(id)->begin(); \
176 while (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) \
177 { \
178 openfluid::core::PcsOrd_t _PCSORDID(id) = (*_UNITSPTRLISTITERID(id))->getProcessOrder(); \
179 _RUN_UNIT_GROUP_THREADED(id,_UNITSPTRLISTITERID(id),_UNITSPTRLISTID(id)->end(),(*_UNITSPTRLISTITERID(id)), \
180 funcptr,(*_UNITSPTRLISTITERID(id))->getProcessOrder() == _PCSORDID(id), ## __VA_ARGS__); \
181 } \
182 }
183
184/**
185 Macro for applying a threaded simulator to each unit of the domain, following their process order
186 @param[in] funcptr member simulator name
187 @param[in] ... extra parameters to pass to the member simulator
188
189 @cond OpenFLUID:completion
190 {
191 "contexts" : ["SIMULATOR", "OBSERVER"],
192 "menupath" : ["Loops"],
193 "title" : "Threaded ordered loop on all spatial units",
194 "text" : "APPLY_ALLUNITS_ORDERED_LOOP_THREADED(%%SEL_START%%FuncPtr%%SEL_END%%)"
195 }
196 @endcond
197*/
198#define APPLY_ALLUNITS_ORDERED_LOOP_THREADED(funcptr,...) \
199 _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,funcptr,## __VA_ARGS__)
200
201
202// =====================================================================
203// =====================================================================
204
205
206#define _APPLY_ALLUNITS_UNORDERED_LOOP_THREADED_WITHID(id,funcptr,...) \
207 openfluid::core::UnitsPtrList_t* _UNITSPTRLISTID(id) = mp_SpatialData->allSpatialUnits(); \
208 if (_UNITSPTRLISTID(id) != nullptr) \
209 { \
210 openfluid::core::UnitsPtrList_t::iterator _UNITSPTRLISTITERID(id) = _UNITSPTRLISTID(id)->begin(); \
211 _RUN_UNIT_GROUP_THREADED(id,_UNITSPTRLISTITERID(id),_UNITSPTRLISTID(id)->end(),(*_UNITSPTRLISTITERID(id)), \
212 funcptr,true,## __VA_ARGS__); \
213 }
214
215/**
216 Macro for applying a threaded simulator to each unit of the domain, without considering process order
217 @param[in] funcptr member simulator name
218 @param[in] ... extra parameters to pass to the member simulator
219
220 @cond OpenFLUID:completion
221 {
222 "contexts" : ["SIMULATOR", "OBSERVER"],
223 "menupath" : ["Loops"],
224 "title" : "Threaded ordered loop on all spatial units",
225 "text" : "APPLY_ALLUNITS_LOOP_THREADED(%%SEL_START%%FuncPtr%%SEL_END%%)"
226 }
227 @endcond
228*/
229#define APPLY_ALLUNITS_UNORDERED_LOOP_THREADED(funcptr,...) \
230 _APPLY_ALLUNITS_UNORDERED_LOOP_THREADED_WITHID(__LINE__,funcptr,## __VA_ARGS__)
231
232
233#endif /* __OPENFLUID_WARE_THREADEDLOOPMACROS_HPP__ */