00001 /* 00002 * This file is part of openMask © INRIA, CNRS, Universite de Rennes 1 1993-2002, thereinafter the Software 00003 * 00004 * The Software has been developped within the Siames Project. 00005 * INRIA, the University of Rennes 1 and CNRS jointly hold intellectual property rights 00006 * 00007 * The Software has been registered with the Agence pour la Protection des 00008 * Programmes (APP) under registration number IDDN.FR.001.510008.00.S.P.2001.000.41200 00009 * 00010 * This file may be distributed under the terms of the Q Public License 00011 * version 1.0 as defined by Trolltech AS of Norway and appearing in the file 00012 * LICENSE.QPL included in the packaging of this file. 00013 * 00014 * Licensees holding valid specific licenses issued by INRIA, CNRS or Université de Rennes 1 00015 * for the software may use this file in accordance with that specific license 00016 * 00017 */ 00018 #ifndef PsOutputHEADER 00019 #define PsOutputHEADER 00020 00021 #include <PsOutputNT.h> 00022 #include <PsnAbstractFifo.h> 00023 #include <typeinfo> 00024 #include <PsPolator.h> 00025 #include <PsName.h> 00026 #include <PsController.h> 00027 #include <PsSimulatedObject.h> 00028 #include <PsSensitiveInput.h> 00029 #include <PsUnInitialisedOutputException.h> 00030 #include <PsnMutexLock.h> 00031 00032 #include "PsnSystemMemoryManager.h" 00033 #include "PsnCurrentActiveObject.h" 00034 00035 template <typename Type> class PsOutputAlias ; 00036 00053 template <typename Type> 00054 class PsOutput : public PsOutputNT 00055 { 00056 public : 00057 00064 PsOutput (const PsName & outputName, 00065 PsSimulatedObject & owner, 00066 const int historySize, 00067 PsPolatorNT * polator = NULL ) ; 00068 00071 virtual ~PsOutput (void) ; 00072 00073 00082 virtual const Type & get (int & distanceToExactValue, 00083 const int precisionLevel, 00084 const PsDate & deltaT, 00085 Type & calculatedResult ) const ; 00086 00087 00090 virtual const Type & getLastExactValue () const ; 00091 00092 00095 virtual const PsDate & getDateOfLastExactValue () const ; 00096 00097 00101 virtual void set ( const Type & newValue ) ; 00102 00103 00107 virtual void suggest ( const Type & suggestedValue ) ; 00108 00109 00112 virtual Type & getNextPlaceHolder() ; 00113 00116 virtual void setInPlace ( const Type & ) ; 00117 00118 00121 virtual void connectedMyself(PsInputNT * input) ; 00122 00123 00126 virtual void disconnectedMyself(PsInputNT * input) ; 00127 00128 00132 00135 virtual void extract (istream & = cin) ; 00136 00139 virtual void insertInStream (ostream & = cout) const ; 00140 00141 00145 virtual void pack (PsOutgoingSynchronisationMessage &) const ; 00146 00147 00151 virtual void packAllValues (PsOutgoingSynchronisationMessage &) const ; 00152 00153 00157 virtual void unpack (PsIncomingSynchronisationMessage &) ; 00158 00162 virtual void unpackAllValues (PsIncomingSynchronisationMessage &) ; 00164 00165 00169 virtual void printDebuggingInformation ( ostream & err ) const ; 00170 00173 void printHistory () const ; 00174 00176 virtual void empty () ; 00177 00181 virtual void setUsedOutput(PsOutput<Type> * output) ; 00182 00184 virtual void setAlias(PsOutputAlias<Type> * output) ; 00185 00187 virtual void unsetAlias () ; 00188 00190 virtual PsOutput<Type> * getUsedOutput( void ) const ; 00191 00192 00194 virtual PsOutputAlias<Type> * getAlias ( void ) const ; 00195 00196 00198 protected : 00202 virtual void setValidity(bool); 00203 00205 friend class PsOutputAlias<Type> ; 00206 00208 virtual void notifyConnectedSensitiveInputs(); 00209 00211 virtual const Type & localGet (int & validiteRes, 00212 const int niveauInterpol, 00213 const PsDate & deltaT, 00214 Type & resultPlaceHolder) const ; 00215 00216 00218 virtual void localInsert (ostream & = cout) const ; 00219 00221 PsOutputAlias<Type> * _aliasOfOutput ; 00222 00224 PsOutput<Type> * _usedOutput ; 00225 00227 PsnAbstractFifo <Type> * _history ; 00228 00230 const PsDate & _date ; 00231 00232 public: 00234 PsPolator <Type> * _polator; 00235 00236 protected: 00238 list<PsSensitiveInput <Type> *> _listOfConnectedSensitiveInputs; 00239 00241 list<PsInput <Type> *> _listOfConnectedUnsensitiveInputs; 00242 00244 bool _sensitiveInputsConnected ; 00245 00249 PsnMutexLock _myMutex ; 00250 00252 bool _validity ; 00253 } ; // PsOutput 00254 00255 #if defined(_MOME) || !defined(_SGI) 00256 #include <PsMomeOutput.h> 00257 #endif 00258 00259 //----------------------------------------------------------------- 00260 #include "PsOutputAlias.h" 00261 00262 template <typename Type> 00263 inline PsOutput<Type>::PsOutput (const PsName & outputName, 00264 PsSimulatedObject & owner, 00265 const int historyLength, 00266 PsPolatorNT * polator) 00267 : PsAttribute(owner, outputName), 00268 PsOutputNT (owner, outputName), 00269 _aliasOfOutput ( NULL ), 00270 _date ( owner.getController().getSimulatedDate() ), 00271 _sensitiveInputsConnected ( false ), 00272 _validity ( false ) 00273 { 00274 /* thread safety assessement : 00275 thread safe because only on construction of the object 00276 */ 00277 00278 00279 #ifdef _DEBUGTYPEUTIL 00280 cout << "PsOutput<Type>::PsOutput () constructor" << endl; 00281 #endif 00282 00283 if ( polator == NULL ) 00284 // tous les types ont une methode static qui crait leur polator par defaut 00285 { 00286 Type aTypeInstance ; // because createPolator isn't static 00287 00288 _polator = static_cast<PsPolator <Type> *>(aTypeInstance.createPolator()) ; 00289 00290 if ( _polator==NULL ) 00291 { 00292 cerr<<"PsOutput<"<<typeid(Type).name()<<">::PsOutput : the created polator of " 00293 <<typeid(aTypeInstance).name()<<" isn't of type PsPolator <"<<typeid(Type).name()<<"> *"<<endl; 00294 } 00295 } 00296 else 00297 { 00298 _polator = dynamic_cast<PsPolator <Type> *>(polator) ; 00299 00300 if (_polator==NULL) 00301 { 00302 cerr<<"PsOutput<"<<typeid(Type).name()<<">::PsOutput : the created polator of type " 00303 <<typeid(polator).name()<<" isn't of type PsPolator <"<<typeid(Type).name()<<"> *"<<endl; 00304 } 00305 } 00306 if (_polator==NULL) 00307 { 00308 cerr<<"PsOutput<"<<typeid(Type).name()<<">::PsOutput : problem in creating the appropriate polator for output "<<getName()<<endl; 00309 } 00310 00311 // calculate the appropriate history fifo length 00312 00313 int realSize = historyLength + _polator->getNumberOfNeededValuesForMaxPrecisionPolation(); 00314 00315 _history = new PsnFifo < Type > (realSize) ; 00316 00317 _polator->setFifo(_history); 00318 00319 _usedOutput = this ; 00320 00321 } 00322 00323 //----------------------------------------------------------------- 00324 00325 template <typename Type> 00326 inline PsOutput<Type>::~PsOutput (void) 00327 { 00328 /* thread safety assessement : 00329 thread safe because only one destruction of the object 00330 */ 00331 00332 #ifdef _TYPENAMENOTIMPLICIT 00333 typename 00334 #endif 00335 list<PsSensitiveInput <Type> *>::iterator i; 00336 00337 _myMutex.protect() ; 00338 00339 for (i = _listOfConnectedSensitiveInputs.begin(); 00340 i != _listOfConnectedSensitiveInputs.end(); 00341 i++) 00342 { 00343 (*i)->outputDestroyed(); 00344 } 00345 00346 #ifdef _TYPENAMENOTIMPLICIT 00347 typename 00348 #endif 00349 list<PsInput <Type> *>::iterator j; 00350 00351 for (j = _listOfConnectedUnsensitiveInputs.begin(); 00352 j != _listOfConnectedUnsensitiveInputs.end(); 00353 j++) 00354 { 00355 (*j)->outputDestroyed(); 00356 } 00357 00358 _myMutex.unprotect() ; 00359 00360 if ( _aliasOfOutput != NULL ) _aliasOfOutput->aliasedOutputDeleted () ; 00361 00362 if ( _history != NULL ) delete _history ; 00363 } 00364 00365 //----------------------------------------------------------------- 00366 00367 template <class Type> 00368 inline void PsOutput<Type>::setUsedOutput(PsOutput<Type> * output) 00369 { 00370 /* thread safety assessement : 00371 multiple simultaneous access possible, and doesn't compromise thread safety : last one out wins 00372 */ 00373 00374 _usedOutput = output ; 00375 } 00376 00377 //----------------------------------------------------------------- 00378 00379 template <typename Type> 00380 void PsOutput<Type>::setValidity(bool b) { 00381 /* thread safety assessement : 00382 protected method, used to change protected member : thread safety should be insured by callers 00383 */ 00384 00385 _validity = b ; 00386 } 00387 00388 //----------------------------------------------------------------- 00389 00390 template <typename Type> 00391 inline void PsOutput<Type>::unsetAlias() 00392 { 00393 /* thread safety assessement : 00394 multiple simultaneous access possible, but they don't compromise thread safety : last one out wins 00395 */ 00396 _aliasOfOutput = NULL ; 00397 setUsedOutput ( this ) ; 00398 } 00399 00400 00401 //----------------------------------------------------------------- 00402 00403 template <typename Type> 00404 inline void PsOutput<Type>::setAlias(PsOutputAlias<Type> * output) 00405 { 00406 /* thread safety assessement : 00407 multiple simultaneous access possible, but they don't compromise thread safety : last one out wins 00408 */ 00409 _aliasOfOutput = output ; 00410 } 00411 00412 //----------------------------------------------------------------- 00413 00414 template <typename Type> 00415 inline PsOutput<Type> * PsOutput<Type>::getUsedOutput( void ) const 00416 { 00417 /* thread safety assessement : 00418 protected method 00419 multiple simultaneous access possible, but as long as this method is only used onced by each access patern, the PsOuptut stays coherant 00420 */ 00421 return _usedOutput ; 00422 } 00423 00424 00425 //----------------------------------------------------------------- 00426 00427 template <typename Type> 00428 inline PsOutputAlias<Type> * PsOutput<Type>::getAlias(void) const 00429 { 00430 /* thread safety assessement : 00431 protected method 00432 multiple simultaneous access possible, but as long as this method is only used onced by each access patern, the PsOuptut stays coherant 00433 */ 00434 return _aliasOfOutput ; 00435 } 00436 00437 //----------------------------------------------------------------- 00438 00439 template <typename Type> 00440 inline const Type & PsOutput<Type>::get(int & validiteRes, 00441 const int niveauInterpol, 00442 const PsDate & deltaT, 00443 Type & resultPlaceHolder ) const 00444 { 00445 /* thread safety assessement : 00446 As thread safe as localGet 00447 */ 00448 #ifdef _DEBUGTYPEUTIL 00449 cerr<<"PsOutput<Type>::get"<<endl; 00450 cerr<<"OutputUtilisée : "<<getUsedOutpute()<<endl; 00451 cerr<<"file : "<<_history<<endl; 00452 _history->printDebuggingInformation() ; 00453 informations(); 00454 #endif 00455 assert( getUsedOutput () != NULL ) ; 00456 return getUsedOutput ()->localGet(validiteRes,niveauInterpol,deltaT,resultPlaceHolder); 00457 } 00458 00459 //----------------------------------------------------------------- 00460 00461 template <typename Type> 00462 const Type & PsOutput<Type>::localGet(int & validiteRes, 00463 const int niveauInterpol, 00464 const PsDate & deltaT, 00465 Type & resultPlaceHolder) const 00466 { 00467 /* thread safety assessement : 00468 As thread safe as polate from PsInterplateur. But be careful : in a multithreaded environment this member function can generate more exceptions than expected 00469 */ 00470 touch() ; 00471 if (!_validity) 00472 { 00473 HeapStackTop usualContext( HeapStackTop::getSystemMemoryManager() ); 00474 PsUnInitialisedOutputException exception(*this,"PsOutput<Type>::localGet \n"); 00475 throw exception; 00476 } 00477 else 00478 { 00479 #ifdef _DEBUGTYPEUTIL 00480 cerr<<"PsOutput<Type>::localGet"<<endl; 00481 cerr<<owner.getController().getSimulatedDate()<<endl; 00482 cerr<<"Interpolateur : "<<_polator<<endl; 00483 #endif 00484 PsDate date = _owner.getController().getSimulatedDate() - deltaT ; 00485 return _polator->polate(niveauInterpol, date,validiteRes, resultPlaceHolder); 00486 } 00487 } 00488 00489 template <typename Type> 00490 void PsOutput<Type>::notifyConnectedSensitiveInputs() { 00491 00492 /* thread safety assessement : 00493 mutex protected 00494 */ 00495 if ( _sensitiveInputsConnected ) 00496 { 00497 // with sensitive inputs connected, it is as if the output value was read at each step 00498 touch() ; 00499 #ifdef _TYPENAMENOTIMPLICIT 00500 typename 00501 #endif 00502 list<PsSensitiveInput <Type> *>::iterator i; 00503 00504 _myMutex.protect() ; 00505 00506 for (i=_listOfConnectedSensitiveInputs.begin() ; 00507 i!=_listOfConnectedSensitiveInputs.end() ; 00508 i++ ) { 00509 #ifdef _DEBUGALIAS 00510 cerr<<"PsOutput<Type>::notifyConnectedSensitiveInputs : one to notify"<<endl; 00511 #endif 00512 (*i)->signalChange(); 00513 #ifdef _DEBUGALIAS 00514 cerr<<"PsOutput<Type>::notifyConnectedSensitiveInputs : one notified"<<endl; 00515 #endif 00516 } 00517 _myMutex.unprotect() ; 00518 } 00519 } 00520 00521 template <typename Type> 00522 void PsOutput<Type>::connectedMyself(PsInputNT * input) { 00523 00524 /* thread safety assessement : 00525 critical data is mutex protected 00526 */ 00527 touch() ; 00528 PsSensitiveInput <Type> * inputSensible=dynamic_cast< PsSensitiveInput <Type> *>(input); 00529 if (inputSensible!=NULL) 00530 { 00531 #ifdef _DEBUGALIAS 00532 cerr<<"PsOutput<Type>::connectedMyself"<<input<<endl; 00533 #endif 00534 _myMutex.protect () ; 00535 00536 _listOfConnectedSensitiveInputs.push_back(inputSensible); 00537 00538 _sensitiveInputsConnected = true ; 00539 00540 _myMutex.unprotect () ; 00541 } 00542 else 00543 { 00544 _myMutex.protect () ; 00545 00546 PsInput<Type> * standardInput = dynamic_cast<PsInput<Type> *> (input) ; 00547 00548 assert (standardInput != NULL ) ; 00549 _listOfConnectedUnsensitiveInputs.push_back ( standardInput ) ; 00550 00551 _myMutex.unprotect () ; 00552 } 00553 } 00554 00555 00556 template <typename Type> 00557 void PsOutput<Type>::disconnectedMyself(PsInputNT * input) { 00558 #ifdef _DEBUGALIAS 00559 cerr<<"PsOutput<Type>::disconnectedMyself"<<endl; 00560 #endif 00561 00562 /* thread safety assessement : 00563 critical data is mutex protected 00564 */ 00565 00566 PsSensitiveInput <Type> * inputSensible=dynamic_cast< PsSensitiveInput <Type> *>(input); 00567 00568 if (inputSensible!=NULL) 00569 { 00570 00571 _myMutex.protect () ; 00572 00573 _listOfConnectedSensitiveInputs.remove(inputSensible); 00574 00575 if ( _listOfConnectedSensitiveInputs.empty() ) _sensitiveInputsConnected = false ; 00576 00577 _myMutex.unprotect () ; 00578 00579 } 00580 else 00581 { 00582 00583 _myMutex.protect () ; 00584 00585 PsInput <Type> * unsensitiveInput = dynamic_cast< PsInput <Type> *>(input); 00586 00587 _listOfConnectedUnsensitiveInputs.remove(unsensitiveInput); 00588 00589 _myMutex.unprotect () ; 00590 00591 } 00592 } 00593 00594 //----------------------------------------------------------------- 00595 00596 template <typename Type> 00597 inline void PsOutput<Type>::set (const Type & newValue ) 00598 { 00599 00601 assert (&_owner == PsnCurrentActiveObject::getCurrentActiveObject() || 00602 PsnCurrentActiveObject::getCurrentActiveObject() == & _owner.getController() || 00603 PsnCurrentActiveObject::getCurrentActiveObject() == NULL ) ; 00604 00605 /* thread safety assessement : 00606 localGet and set could collide. Thread safety can only be assured if the fifo and the interpolator are thread safe with respect to the value in the fifo. 00607 only one set at a time. 00608 */ 00609 00610 if (_validity) 00611 { 00612 const Type & oldValue = _history->getPreceedingValue(0); 00613 if( newValue != oldValue ) //comparaison has to be done before the set, because we're working on references and that there can be a double set (bug corrected by D. Margery) 00614 { 00615 _history->set ( newValue, _date) ; 00616 notifyConnectedSensitiveInputs() ; 00617 } 00618 else 00619 { 00620 _history->set ( newValue, _date) ; 00621 } 00622 } 00623 else { 00624 _history->set (newValue, _date) ; 00625 setValidity(true) ; 00626 notifyConnectedSensitiveInputs(); 00627 } 00628 } 00629 00630 //----------------------------------------------------------------- 00631 00632 template <typename Type> 00633 inline void PsOutput<Type>::extract (istream & in) { 00634 00635 /* thread safety assessement : 00636 localGet and extract could collide. Thread safety can only be assured if the fifo and the interpolator are thread safe with respect to the values in the fifo. 00637 only one extract at a time. 00638 */ 00639 00640 if (_validity) 00641 { 00642 const Type & oldValue=_history->getPreceedingValue(0); 00643 in >> *_history ; 00644 if(_history->getPreceedingValue(0)!=oldValue) //double extract won't happen 00645 { 00646 notifyConnectedSensitiveInputs(); 00647 } 00648 } 00649 else 00650 { 00651 in >> *_history ; 00652 setValidity(true) ; 00653 notifyConnectedSensitiveInputs(); 00654 } 00655 } 00656 00657 template <typename Type> 00658 void PsOutput<Type>::pack (PsOutgoingSynchronisationMessage & out) const 00659 { 00660 //cerr<<"PsOutput<Type>::pack"<<endl; 00661 //packs the name of the output, then any usefull information 00662 /* thread safety assement 00663 thread safe : collides with set and localInsert on the PsnAbstractFifo. But they should only be activated by the owner. So as long as the owner isn't multithreaded... 00664 nota : in a multithreaded environment this member function could generate more exceptions than expected 00665 */ 00666 if (_validity) 00667 { 00668 if ( out.getMessageDate() == _history->getPreceedingDate ( 0 ) ) 00669 { 00670 getName ().pack ( out ) ; 00671 _history->pack( out ) ; 00672 } 00673 } 00674 //else : do not pack anything, therefore mirror will remain uninitialised 00675 // cerr<<"PsOutput<Type>:"<<this<<":pack done"<<endl; 00676 } 00677 00678 00679 00680 template <typename Type> 00681 void PsOutput<Type>::packAllValues (PsOutgoingSynchronisationMessage & out) const 00682 { 00683 //cerr<<"PsOutput<Type>::packAllValues"<<endl; 00684 //packs the name of the output, then all initial information 00685 /* thread safety assement 00686 thread safe : collides with set and localInsert on the PsnAbstractFifo. But they should only be activated by the owner. So as long as the owner isn't multithreaded, or that the kernel doesn't call this member function during activation of the owner... 00687 nota : in a multithreaded environment this member function could generate more exceptions than expected 00688 */ 00689 if (_validity) 00690 { 00691 getName ().pack ( out ) ; 00692 _history->packAllValues( out ) ; 00693 } 00694 //else : do not pack anything, therefore mirror will remain uninitialised 00695 // cerr<<"PsOutput<Type>:"<<this<<":packAllVAlues done"<<endl; 00696 } 00697 00698 00699 00700 template <typename Type> 00701 void PsOutput<Type>::unpack (PsIncomingSynchronisationMessage & in) 00702 { 00703 // shouldn't unpack the name, but all other usefull information packed 00704 /* thread safety assessement : 00705 localGet and extract could collide. Thread safety can only be assured if the fifo and the interpolator are thread safe with respect to the values in the fifo. 00706 only one extract at a time. 00707 */ 00708 00709 if (_validity) 00710 { 00711 const Type & oldValue = _history->getPreceedingValue(0); 00712 _history->unpack ( in ) ; 00713 if(_history->getPreceedingValue(0) != oldValue) //double extract won't happen 00714 { 00715 notifyConnectedSensitiveInputs(); 00716 } 00717 } 00718 else 00719 { 00720 _history->unpack ( in ) ; 00721 setValidity(true) ; 00722 notifyConnectedSensitiveInputs() ; 00723 } 00724 } 00725 00726 00727 00728 template <typename Type> 00729 void PsOutput<Type>::unpackAllValues (PsIncomingSynchronisationMessage & in) 00730 { 00731 // shouldn't unpack the name, but all other usefull information packed 00732 /* thread safety assessement : 00733 localGet and extract could collide. Thread safety can only be assured if the fifo and the interpolator are thread safe with respect to the values in the fifo. 00734 only one extract at a time. 00735 */ 00736 00737 if (_validity) 00738 { 00739 // only in the case a suggested values was given at connection 00740 const Type & oldValue = _history->getPreceedingValue(0); 00741 _history->unpackAllValues ( in ) ; 00742 if(_history->getPreceedingValue(0) != oldValue) //double extract won't happen 00743 { 00744 notifyConnectedSensitiveInputs(); 00745 } 00746 } 00747 else 00748 { 00749 _history->unpackAllValues ( in ) ; 00750 setValidity(true) ; 00751 } 00752 } 00753 00754 00755 template <typename Type> 00756 inline void PsOutput<Type>::insertInStream (ostream & out) const { 00757 /*thread safety assessement : 00758 As thread safe as localInsert 00759 */ 00760 cerr<<"PsOutput<Type>::insertInStream"<<endl; 00761 getUsedOutput()->localInsert(out); 00762 } 00763 00764 00765 template <typename Type> 00766 inline void PsOutput<Type>::localInsert (ostream & out) const { 00767 /* thread safety assement 00768 thread safe : collides with set on the PsnAbstractFifo. But they should only be activated by the owner. So as lmong as the owner isn't multithreaded... 00769 nota : in a multithreaded environment this member function could generate more exceptions than expected 00770 */ 00771 if (!_validity) 00772 { 00773 HeapStackTop usualContext(HeapStackTop::getSystemMemoryManager() ); 00774 PsUnInitialisedOutputException exception(*this,"PsOutput<Type>::localInsert\n"); 00775 exception<<"Cannot read uninitailised output of "<<_owner.getName().getCString(); 00776 throw exception; 00777 } 00778 else 00779 { 00780 out << *_history << " " ; 00781 } 00782 } 00783 00784 template <typename Type> 00785 inline void PsOutput<Type>::printHistory () const { 00786 /* thread safety assessement : 00787 const method : should be thread safe if printDebuggingInformation of PsnAbstractFifo is thread safe 00788 */ 00789 _history->printDebuggingInformation () ; 00790 } 00791 00792 //----------------------------------------------------------------- 00793 00794 template <typename Type> 00795 inline void PsOutput<Type>::printDebuggingInformation (ostream & err ) const 00796 { 00797 /* thread safety assessement : 00798 const method : thread safe. shown value may not be a coherant image of an PsOutput 00799 */ 00800 err << "**********************************************************" << endl; 00801 err << "Class PsOutput" << endl; 00802 err << "Owner : " << _owner.getName () << endl; 00803 err << "Output Name : "<< _name <<endl; 00804 err << "Type of output : "<< typeid(Type).name() << endl ; 00805 err << "Output primary alias : " << getAlias() << endl ; 00806 err << "Used Output : " << getUsedOutput () << endl ; 00807 err << "History Fifo: "<<_history <<endl; 00808 } 00809 00810 //----------------------------------------------------------------- 00811 00812 template <typename Type> 00813 inline void PsOutput<Type>::empty (void) { 00814 /* thread safety assessement : 00815 as thread safe as clear of fifo. Only one simultaneous acces possible (in theory). 00816 */ 00817 // MIPSPRO 7.3.1.2 workaround 00818 static PsSensitiveInput<Type> toto (getName(), _owner, false) ; 00819 _history->clear () ; 00820 setValidity(false) ; 00821 } 00822 00823 00824 template <typename Type> 00825 inline const Type & PsOutput<Type>::getLastExactValue () const 00826 { 00827 touch() ; 00828 // this bypasses any Polator 00829 if (_history->getNumberOfPresentValues(1) >= 1 ) //if a value is stored 00830 { 00831 return _history->getPreceedingValue ( 0 ) ; 00832 } 00833 else 00834 { 00835 HeapStackTop usualContext(HeapStackTop::getSystemMemoryManager()); 00836 PsUnInitialisedOutputException exception(*this,"PsOutput<Type>::getLastExactValue\n"); 00837 exception<<"Impossible to get a value from an uninitialised output of "<<_owner.getName().getCString(); 00838 throw exception; 00839 } 00840 } 00841 00842 00843 template <typename Type> 00844 inline const PsDate & PsOutput<Type>::getDateOfLastExactValue () const 00845 { 00846 touch() ; 00847 // this bypasses any Polator 00848 if (_history->getNumberOfPresentValues(1) >= 1 ) //if a value is stored 00849 { 00850 return _history->getPreceedingDate ( 0 ) ; 00851 } 00852 else 00853 { 00854 HeapStackTop usualContext(HeapStackTop::getSystemMemoryManager() ); 00855 PsUnInitialisedOutputException exception(*this,"PsOutput<Type>::getLastExactValue\n"); 00856 exception<<"Impossible to get a value from an uninitialised output of "<<_owner.getName().getCString(); 00857 throw exception; 00858 } 00859 } 00860 00861 00862 template <typename Type> 00863 inline Type & PsOutput<Type>::getNextPlaceHolder () 00864 { 00865 return _history->getNextPlaceHolder() ; 00866 } 00867 00868 00869 template <typename Type> 00870 inline void PsOutput<Type>::setInPlace( const Type & newValue ) 00871 { 00872 00873 if (_validity) 00874 { 00875 const Type & oldValue = _history->getPreceedingValue(0); 00876 00877 if( newValue != oldValue) //comparaison has to be done before setInPlace, because there can be a double setInPlace and we're working on references (bug corrected by D. Margery) 00878 { 00879 _history->setInPlace ( newValue, _date ) ; 00880 notifyConnectedSensitiveInputs(); 00881 } 00882 else 00883 { 00884 _history->setInPlace ( newValue, _date ) ; 00885 } 00886 } 00887 else 00888 { 00889 _history->setInPlace ( newValue, _date) ; 00890 setValidity(true) ; 00891 notifyConnectedSensitiveInputs(); 00892 } 00893 } 00894 00895 00896 template <typename Type> 00897 inline void PsOutput<Type>::suggest( const Type & newValue ) 00898 { 00899 if (!_validity) 00900 { 00901 _history->set ( newValue , _owner.getController ().getSimulatedDate () ) ; 00902 setValidity(true) ; 00903 notifyConnectedSensitiveInputs(); 00904 } 00905 } 00906 00907 #endif 00908 00909 00910 00911
| Documentation generated on Mon Nov 25 15:25:02 2002 |
Generated with doxygen 1.2.12 by Dimitri van Heesch , 1997-2001 |