Salome HOME
Fix missing returns.
[modules/yacs.git] / src / engine / Pool.cxx
1 // Copyright (C) 2006-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "Pool.hxx"
21 #include "Any.hxx"
22
23 #include <sstream>
24 #include <set>
25
26 using namespace YACS::ENGINE;
27
28 Any *Pool::ExpData::NOT_USED_NOR_COMPUTED = 0;
29
30 Any *Pool::ExpData::USED_BUT_NOT_COMPUTED_YET = (Any *) 1;
31
32 const char Pool::MESSAGEFORUNXSTNGID[]="The id specified not exists. Unable to handle with. Either internal error, or invalid use of Pool from Optimizer Algorithm";
33
34 Pool::ExpData::ExpData(Any *inValue, unsigned char priority):_in(inValue),_out(NOT_USED_NOR_COMPUTED),_priority(priority)
35 {
36   if(_in)
37     _in->incrRef();
38 }
39
40 Pool::ExpData::ExpData(const ExpData& other):_in(other._in),_out(other._out),_priority(other._priority)
41 {
42   if(_in)
43     _in->incrRef();
44 }
45
46 Pool::ExpData::~ExpData()
47 {
48   if(_in)
49     _in->decrRef();
50   if(_out!=USED_BUT_NOT_COMPUTED_YET && _out!=NOT_USED_NOR_COMPUTED)
51     _out->decrRef();
52 }
53
54 /*!
55  * When used _out is assumed to be equal to 'USED_BUT_NOT_COMPUTED_YET' before call.
56  */
57 void Pool::ExpData::setOutValue(Any *outValue)
58 {
59   if(_out!=USED_BUT_NOT_COMPUTED_YET && _out!=NOT_USED_NOR_COMPUTED)
60     _out->decrRef();//should absolutely never happend.
61   _out=outValue;
62   _out->incrRef();
63 }
64
65 /*!
66  * When called _out is assumed to be equal to 'NOT_USED_NOR_COMPUTED' before call.
67  */
68 void Pool::ExpData::markItAsInUse()
69 {
70   _out=USED_BUT_NOT_COMPUTED_YET;
71 }
72
73 bool Pool::ExpData::isLaunchable() const
74 {
75   return _out==NOT_USED_NOR_COMPUTED;
76 }
77
78 int Pool::getCurrentId() const 
79
80   if(empty())
81     throw YACS::Exception("no current case set in pool");
82   else
83     return _currentCase->first; 
84 }
85 Any *Pool::getCurrentInSample() const 
86
87   if(empty())
88     throw YACS::Exception("no current case set in pool");
89   else
90     return (*_currentCase).second.inValue(); 
91 }
92
93 Any *Pool::getCurrentOutSample() const 
94
95   if(empty())
96     throw YACS::Exception("no current case set in pool");
97   else
98     return (*_currentCase).second.outValue(); 
99 }
100
101 Any *Pool::getOutSample(int id)
102 {
103   if(empty())
104     throw YACS::Exception("no current case set in pool");
105
106   std::list< std::pair<int, ExpData> >::iterator iter;
107   for(iter=_container.begin();iter!=_container.end();iter++)
108     if((*iter).first==id)
109         return (*iter).second.outValue();
110   throw YACS::Exception("no current case set in pool");
111 }
112
113
114 //! Push a sample. \b WARNING inSample ownership is released to current Pool instance (this) !
115 void Pool::pushInSample(int id, Any *inSample, unsigned char priority)
116 {
117   std::pair<int, ExpData> eltToAdd(id,Pool::ExpData(inSample,priority));
118   _container.push_back(eltToAdd);
119   inSample->decrRef();
120 }
121
122 void Pool::destroyAll()
123 {
124   _container.clear();
125 }
126
127 void Pool::destroyCurrentCase()
128 {
129   if(!_container.empty())
130     _container.erase(_currentCase);
131 }
132
133 /*!
134  *
135  * This method is typically called by OptimizerNode to check the consistency, that is to say that optimizer algorithm has not
136  * corrupted 'this'.
137  *
138  */
139 void Pool::checkConsistency()
140 {
141   // First check unicity of ids.
142   std::set<int> ids;
143   std::list< std::pair<int, ExpData> >::iterator iter;
144   for(iter=_container.begin();iter!=_container.end();iter++)
145     {
146       std::pair< std::set<int>::iterator, bool > verdict=ids.insert((*iter).first);
147       if(verdict.second)
148         {
149           std::ostringstream what;
150           what << "Id with value : " << (*iter).first << " appears several times.";
151           throw Exception(what.str());
152         }
153     }
154 }
155
156 /*!
157  * \throw See the \b throw case of pushOutSampleAt method.
158  */
159 void Pool::setCurrentId(int id)
160 {
161   std::list< std::pair<int, ExpData> >::iterator iter;
162   for(iter=_container.begin();iter!=_container.end();iter++)
163     if((*iter).first==id)
164       {
165         _currentCase=iter;
166         break;
167       }
168   if(iter==_container.end())
169     throw Exception(MESSAGEFORUNXSTNGID);
170 }
171
172 /*!
173  *
174  * Push a result of case discriminated by \b id. It also sets the \b _currentCase pointer on the case discriminated by \b id.
175  * So after this call, the call to setCurrentId with the same \b id is useless.
176  * \throw When case id is not found in 'this'. This is particulary true, if not an internal error, when optimizer algorithm  
177  *        has destroyed a case id different from its id.
178  *
179  */
180 void Pool::putOutSampleAt(int id, Any *outValue)
181 {
182   std::list< std::pair<int, ExpData> >::iterator iter;
183   for(iter=_container.begin();iter!=_container.end();iter++)
184     if((*iter).first==id)
185       {
186         _currentCase=iter;
187         (*iter).second.setOutValue(outValue);
188         break;
189       }
190   if(iter==_container.end())
191     throw Exception(MESSAGEFORUNXSTNGID);
192 }
193
194 /*!
195  *
196  * This method is typically called by OptimizerNode instance owner of 'this' that wants to launch an another job on one branch.
197  * \return : In case there are more jobs to do 2 parameters are returned.
198  *           - \b id to locate the computation to do.
199  *           - \b priority attached.
200  *           - \b value.
201  *           In case no more jobs are required id and priority stay unchanged and the returned value is equal to 0.
202  *
203  */
204 Any *Pool::getNextSampleWithHighestPriority(int& id, unsigned char& priority) const
205 {
206   unsigned char myPriority=0;
207   std::list< std::pair<int, ExpData> >::const_iterator iter,ptToSelected;
208   ptToSelected=_container.end();
209   for(iter=_container.begin();iter!=_container.end();iter++)
210     {
211       if((*iter).second.isLaunchable())
212         if((*iter).second.getPriority()>myPriority || ptToSelected==_container.end())
213           {
214             ptToSelected=iter;
215             myPriority=(*iter).second.getPriority();
216           }
217     }
218   //Search performed. No performing output writings if needed.
219   if(ptToSelected==_container.end())
220     return 0;
221   priority=myPriority;
222   id=(*ptToSelected).first;  
223   return (*ptToSelected).second.inValue();
224 }
225
226 /*!
227  *
228  * Typically called after 'this->destroyCurrentCase' 'this->checkConsistency' and 'this->getNextSampleWithHighestPriority' have been called.
229  * At this point the case with id \b id is marked as in use in order to avoid to be used by an another branch of OptimizerNode.
230  *
231  */
232 void Pool::markIdAsInUse(int id)
233 {
234   std::list< std::pair<int, ExpData> >::iterator iter;
235   for(iter=_container.begin();iter!=_container.end();iter++)
236     if((*iter).first==id)
237       {
238         (*iter).second.markItAsInUse();
239         break;
240       }
241 }
242
243 /*!
244  * Typically called after takeDecision of OptimizerAlg as been performed. If true is returned, that is to say that convergence has been reached.
245  */
246 bool Pool::empty() const
247 {
248   return _container.empty();
249 }