Salome HOME
Update copyrights
[modules/yacs.git] / src / engine / Pool.cxx
1 // Copyright (C) 2006-2019  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   if(iter==_container.end())
111     throw YACS::Exception("no current case set in pool");
112 }
113
114
115 //! Push a sample. \b WARNING inSample ownership is released to current Pool instance (this) !
116 void Pool::pushInSample(int id, Any *inSample, unsigned char priority)
117 {
118   std::pair<int, ExpData> eltToAdd(id,Pool::ExpData(inSample,priority));
119   _container.push_back(eltToAdd);
120   inSample->decrRef();
121 }
122
123 void Pool::destroyAll()
124 {
125   _container.clear();
126 }
127
128 void Pool::destroyCurrentCase()
129 {
130   if(!_container.empty())
131     _container.erase(_currentCase);
132 }
133
134 /*!
135  *
136  * This method is typically called by OptimizerNode to check the consistency, that is to say that optimizer algorithm has not
137  * corrupted 'this'.
138  *
139  */
140 void Pool::checkConsistency() throw(YACS::Exception)
141 {
142   // First check unicity of ids.
143   std::set<int> ids;
144   std::list< std::pair<int, ExpData> >::iterator iter;
145   for(iter=_container.begin();iter!=_container.end();iter++)
146     {
147       std::pair< std::set<int>::iterator, bool > verdict=ids.insert((*iter).first);
148       if(verdict.second)
149         {
150           std::ostringstream what;
151           what << "Id with value : " << (*iter).first << " appears several times.";
152           throw Exception(what.str());
153         }
154     }
155 }
156
157 /*!
158  * \throw See the \b throw case of pushOutSampleAt method.
159  */
160 void Pool::setCurrentId(int id) throw(YACS::Exception)
161 {
162   std::list< std::pair<int, ExpData> >::iterator iter;
163   for(iter=_container.begin();iter!=_container.end();iter++)
164     if((*iter).first==id)
165       {
166         _currentCase=iter;
167         break;
168       }
169   if(iter==_container.end())
170     throw Exception(MESSAGEFORUNXSTNGID);
171 }
172
173 /*!
174  *
175  * Push a result of case discriminated by \b id. It also sets the \b _currentCase pointer on the case discriminated by \b id.
176  * So after this call, the call to setCurrentId with the same \b id is useless.
177  * \throw When case id is not found in 'this'. This is particulary true, if not an internal error, when optimizer algorithm  
178  *        has destroyed a case id different from its id.
179  *
180  */
181 void Pool::putOutSampleAt(int id, Any *outValue) throw(YACS::Exception)
182 {
183   std::list< std::pair<int, ExpData> >::iterator iter;
184   for(iter=_container.begin();iter!=_container.end();iter++)
185     if((*iter).first==id)
186       {
187         _currentCase=iter;
188         (*iter).second.setOutValue(outValue);
189         break;
190       }
191   if(iter==_container.end())
192     throw Exception(MESSAGEFORUNXSTNGID);
193 }
194
195 /*!
196  *
197  * This method is typically called by OptimizerNode instance owner of 'this' that wants to launch an another job on one branch.
198  * \return : In case there are more jobs to do 2 parameters are returned.
199  *           - \b id to locate the computation to do.
200  *           - \b priority attached.
201  *           - \b value.
202  *           In case no more jobs are required id and priority stay unchanged and the returned value is equal to 0.
203  *
204  */
205 Any *Pool::getNextSampleWithHighestPriority(int& id, unsigned char& priority) const
206 {
207   unsigned char myPriority=0;
208   std::list< std::pair<int, ExpData> >::const_iterator iter,ptToSelected;
209   ptToSelected=_container.end();
210   for(iter=_container.begin();iter!=_container.end();iter++)
211     {
212       if((*iter).second.isLaunchable())
213         if((*iter).second.getPriority()>myPriority || ptToSelected==_container.end())
214           {
215             ptToSelected=iter;
216             myPriority=(*iter).second.getPriority();
217           }
218     }
219   //Search performed. No performing output writings if needed.
220   if(ptToSelected==_container.end())
221     return 0;
222   priority=myPriority;
223   id=(*ptToSelected).first;  
224   return (*ptToSelected).second.inValue();
225 }
226
227 /*!
228  *
229  * Typically called after 'this->destroyCurrentCase' 'this->checkConsistency' and 'this->getNextSampleWithHighestPriority' have been called.
230  * 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.
231  *
232  */
233 void Pool::markIdAsInUse(int id)
234 {
235   std::list< std::pair<int, ExpData> >::iterator iter;
236   for(iter=_container.begin();iter!=_container.end();iter++)
237     if((*iter).first==id)
238       {
239         (*iter).second.markItAsInUse();
240         break;
241       }
242 }
243
244 /*!
245  * Typically called after takeDecision of OptimizerAlg as been performed. If true is returned, that is to say that convergence has been reached.
246  */
247 bool Pool::empty() const
248 {
249   return _container.empty();
250 }