Salome HOME
copy tag mergefrom_BR_V0_1_CC_Salome_04oct07
[modules/yacs.git] / src / engine / Pool.cxx
1 #include "Pool.hxx"
2 #include "Any.hxx"
3
4 #include <sstream>
5 #include <set>
6
7 using namespace YACS::ENGINE;
8
9 Any *Pool::ExpData::NOT_USED_NOR_COMPUTED = 0;
10
11 Any *Pool::ExpData::USED_BUT_NOT_COMPUTED_YET = (Any *) 1;
12
13 const char Pool::MESSAGEFORUNXSTNGID[]="The id specified not exists. Unable to handle with. Either internal error, or invalid use of Pool from Optimizer Algorithm";
14
15 Pool::ExpData::ExpData(Any *inValue, unsigned char priority):_in(inValue),_out(NOT_USED_NOR_COMPUTED),_priority(priority)
16 {
17   if(_in)
18     _in->incrRef();
19 }
20
21 Pool::ExpData::ExpData(const ExpData& other):_in(other._in),_out(other._out),_priority(other._priority)
22 {
23   if(_in)
24     _in->incrRef();
25 }
26
27 Pool::ExpData::~ExpData()
28 {
29   if(_in)
30     _in->decrRef();
31   if(_out!=USED_BUT_NOT_COMPUTED_YET && _out!=NOT_USED_NOR_COMPUTED)
32     _out->decrRef();
33 }
34
35 /*!
36  * When used _out is assumed to be equal to 'USED_BUT_NOT_COMPUTED_YET' before call.
37  */
38 void Pool::ExpData::setOutValue(Any *outValue)
39 {
40   if(_out!=USED_BUT_NOT_COMPUTED_YET && _out!=NOT_USED_NOR_COMPUTED)
41     _out->decrRef();//should absolutely never happend.
42   _out=outValue;
43   _out->incrRef();
44 }
45
46 /*!
47  * When called _out is assumed to be equal to 'NOT_USED_NOR_COMPUTED' before call.
48  */
49 void Pool::ExpData::markItAsInUse()
50 {
51   _out=USED_BUT_NOT_COMPUTED_YET;
52 }
53
54 bool Pool::ExpData::isLaunchable() const
55 {
56   return _out==NOT_USED_NOR_COMPUTED;
57 }
58
59 //! Push a sample. \b WARNING inSample ownership is released to current Pool instance (this) !
60 void Pool::pushInSample(int id, Any *inSample, unsigned char priority)
61 {
62   std::pair<int, ExpData> eltToAdd(id,Pool::ExpData(inSample,priority));
63   _container.push_back(eltToAdd);
64   inSample->decrRef();
65 }
66
67 void Pool::destroyAll()
68 {
69   _container.clear();
70 }
71
72 void Pool::destroyCurrentCase()
73 {
74   if(!_container.empty())
75     _container.erase(_currentCase);
76 }
77
78 /*!
79  *
80  * This method is typically called by OptimizerNode to check the consistency, that is to say that optimizer algorithm has not
81  * corrupted 'this'.
82  *
83  */
84 void Pool::checkConsistency() throw(Exception)
85 {
86   // First check unicity of ids.
87   std::set<int> ids;
88   std::list< std::pair<int, ExpData> >::iterator iter;
89   for(iter=_container.begin();iter!=_container.end();iter++)
90     {
91       std::pair< std::set<int>::iterator, bool > verdict=ids.insert((*iter).first);
92       if(verdict.second)
93         {
94           std::ostringstream what;
95           what << "Id with value : " << (*iter).first << " appears several times.";
96           throw Exception(what.str());
97         }
98     }
99 }
100
101 /*!
102  * \throw See the \b throw case of pushOutSampleAt method.
103  */
104 void Pool::setCurrentId(int id) throw(Exception)
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       {
110         _currentCase=iter;
111         break;
112       }
113   if(iter==_container.end())
114     throw Exception(MESSAGEFORUNXSTNGID);
115 }
116
117 /*!
118  *
119  * Push a result of case discriminated by \b id. It also sets the \b _currentCase pointer on the case discriminated by \b id.
120  * So after this call, the call to setCurrentId with the same \b id is useless.
121  * \throw When case id is not found in 'this'. This is particulary true, if not an internal error, when optimizer algorithm  
122  *        has destroyed a case id different from its id.
123  *
124  */
125 void Pool::putOutSampleAt(int id, Any *outValue) throw(Exception)
126 {
127   std::list< std::pair<int, ExpData> >::iterator iter;
128   for(iter=_container.begin();iter!=_container.end();iter++)
129     if((*iter).first==id)
130       {
131         _currentCase=iter;
132         (*iter).second.setOutValue(outValue);
133         break;
134       }
135   if(iter==_container.end())
136     throw Exception(MESSAGEFORUNXSTNGID);
137 }
138
139 /*!
140  *
141  * This method is typically called by OptimizerNode instance owner of 'this' that wants to launch an another job on one branch.
142  * \return : In case there are more jobs to do 2 parameters are returned.
143  *           - \b id to locate the computation to do.
144  *           - \b priority attached.
145  *           - \b value.
146  *           In case no more jobs are required id and priority stay unchanged and the returned value is equal to 0.
147  *
148  */
149 Any *Pool::getNextSampleWithHighestPriority(int& id, unsigned char& priority) const
150 {
151   unsigned char myPriority=0;
152   std::list< std::pair<int, ExpData> >::const_iterator iter,ptToSelected;
153   ptToSelected=_container.end();
154   for(iter=_container.begin();iter!=_container.end();iter++)
155     {
156       if((*iter).second.isLaunchable())
157         if((*iter).second.getPriority()>myPriority || ptToSelected==_container.end())
158           {
159             ptToSelected=iter;
160             myPriority=(*iter).second.getPriority();
161           }
162     }
163   //Search performed. No performing output writings if needed.
164   if(ptToSelected==_container.end())
165     return 0;
166   priority=myPriority;
167   id=(*ptToSelected).first;  
168   return (*ptToSelected).second.inValue();
169 }
170
171 /*!
172  *
173  * Typically called after 'this->destroyCurrentCase' 'this->checkConsistency' and 'this->getNextSampleWithHighestPriority' have been called.
174  * 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.
175  *
176  */
177 void Pool::markIdAsInUse(int id)
178 {
179   std::list< std::pair<int, ExpData> >::iterator iter;
180   for(iter=_container.begin();iter!=_container.end();iter++)
181     if((*iter).first==id)
182       {
183         (*iter).second.markItAsInUse();
184         break;
185       }
186 }
187
188 /*!
189  * Typically called after takeDecision of OptimizerAlg as been performed. If true is returned, that is to say that convergence has been reached.
190  */
191 bool Pool::empty() const
192 {
193   return _container.empty();
194 }