Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

PsOutput.h

Go to the documentation of this file.
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 

logo OpenMask

Documentation generated on Mon Nov 25 15:25:02 2002

Generated with doxygen 1.2.12 by Dimitri van Heesch ,   1997-2001