All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 LoopMacros.hpp
35  \brief Header of ...
36 
37  \author Jean-Christophe FABRE <fabrejc@supagro.inra.fr>
38  */
39 
40 
41 #ifndef __THREADEDLOOPMACROS_HPP__
42 #define __THREADEDLOOPMACROS_HPP__
43 
44 #include <QtGlobal>
45 
46 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
47 #include <QtConcurrent>
48 #endif
49 
50 #include <QtConcurrentRun>
51 #include <QFutureSynchronizer>
52 
54 
55 // =====================================================================
56 // =====================================================================
57 
58 
59 
60 #define _THREADSYNCID(_id) _M_##_id##_Sync
61 
62 
63 #define _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(id,unitclass,funcptr,...) \
64  openfluid::core::UnitsList_t* _UNITSLISTID(id) = mp_CoreData->getUnits(unitclass)->getList(); \
65  if (_UNITSLISTID(id) != NULL) \
66  { \
67  openfluid::core::UnitsList_t::iterator _UNITSLISTITERID(id) = _UNITSLISTID(id)->begin(); \
68  if (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
69  { \
70  openfluid::core::PcsOrd_t _PCSORDID(id) = _UNITSLISTITERID(id)->getProcessOrder(); \
71  while (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) \
72  { \
73  QFutureSynchronizer<void> _THREADSYNCID(id); \
74  while (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end() && _UNITSLISTITERID(id)->getProcessOrder() == _PCSORDID(id)) \
75  { \
76  try \
77  { \
78  _THREADSYNCID(id).addFuture(QtConcurrent::run(boost::bind(&funcptr,this,&(*_UNITSLISTITERID(id)),## __VA_ARGS__)));\
79  if (_THREADSYNCID(id).futures().size() == OPENFLUID_GetSimulatorMaxThreads())\
80  { \
81  _THREADSYNCID(id).waitForFinished(); \
82  _THREADSYNCID(id).clearFutures(); \
83  }\
84  }\
85  catch(QtConcurrent::UnhandledException& E) \
86  { \
87  throw openfluid::base::FrameworkException("Unknown exception thrown from compute thread"); \
88  } \
89  ++_UNITSLISTITERID(id); \
90  } \
91  _THREADSYNCID(id).waitForFinished(); \
92  _THREADSYNCID(id).clearFutures(); \
93  if (_UNITSLISTITERID(id) != _UNITSLISTID(id)->end()) _PCSORDID(id) = _UNITSLISTITERID(id)->getProcessOrder(); \
94  } \
95  } \
96  }
97 
98 /**
99  Macro for applying a threaded simulator to each unit of a class, following their process order
100  @param[in] unitclass name of the unit class
101  @param[in] funcptr member simulator name
102  @param[in] ... extra parameters to pass to the member simulator
103 */
104 #define APPLY_UNITS_ORDERED_LOOP_THREADED(unitclass,funcptr,...) \
105  _APPLY_UNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,unitclass,funcptr,## __VA_ARGS__)
106 
107 
108 
109 #define _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(id,funcptr,...) \
110  openfluid::core::UnitsPtrList_t* _UNITSPTRLISTID(id) = mp_CoreData->getUnitsGlobally(); \
111  if (_UNITSPTRLISTID(id) != NULL) \
112  { \
113  openfluid::core::UnitsPtrList_t::iterator _UNITSPTRLISTITERID(id) = _UNITSPTRLISTID(id)->begin(); \
114  if (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) \
115  { \
116  openfluid::core::PcsOrd_t _PCSORDID(id) = (*_UNITSPTRLISTITERID(id))->getProcessOrder(); \
117  while (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) \
118  { \
119  QFutureSynchronizer<void> _THREADSYNCID(id); \
120  while (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end() && (*_UNITSPTRLISTITERID(id))->getProcessOrder() == _PCSORDID(id)) \
121  { \
122  try \
123  { \
124  _THREADSYNCID(id).addFuture(QtConcurrent::run(boost::bind(&funcptr,this,(*_UNITSPTRLISTITERID(id)),## __VA_ARGS__)));\
125  if (_THREADSYNCID(id).futures().size() == OPENFLUID_GetSimulatorMaxThreads())\
126  { \
127  _THREADSYNCID(id).waitForFinished(); \
128  _THREADSYNCID(id).clearFutures(); \
129  }\
130  }\
131  catch(QtConcurrent::UnhandledException& E) \
132  { \
133  throw openfluid::base::FrameworkException("Unknown exception thrown from compute thread"); \
134  } \
135  ++_UNITSPTRLISTITERID(id); \
136  } \
137  _THREADSYNCID(id).waitForFinished(); \
138  _THREADSYNCID(id).clearFutures(); \
139  if (_UNITSPTRLISTITERID(id) != _UNITSPTRLISTID(id)->end()) _PCSORDID(id) = (*_UNITSPTRLISTITERID(id))->getProcessOrder(); \
140  } \
141  } \
142  }
143 
144 /**
145  Macro for applying a threaded simulator to each unit of the domain, following their process order
146  @param[in] funcptr member simulator name
147  @param[in] ... extra parameters to pass to the member simulator
148 */
149 #define APPLY_ALLUNITS_ORDERED_LOOP_THREADED(funcptr,...) \
150  _APPLY_ALLUNITS_ORDERED_LOOP_THREADED_WITHID(__LINE__,funcptr,## __VA_ARGS__)
151 
152 
153 
154 
155 // =====================================================================
156 // =====================================================================
157 
158 
159 #endif /* __THREADEDLOOPMACROS_HPP__ */
Header of ...