OMKOutput.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 OutputHEADER
00019 #define OutputHEADER
00020 
00021 #include "OMKOutputNT.h"
00022 #include "OMKAbstractFifo.h"
00023 #include "OMKPolator.h"
00024 #include "OMKName.h"
00025 #include "OMKController.h"
00026 #include "OMKSimulatedObject.h"
00027 #include "OMKUnInitialisedOutputException.h"
00028 #include "OMKCurrentActiveObject.h"
00029 #include <typeinfo>
00030 
00031 namespace OMK
00032 {
00033   template< typename T > class OutputAlias ;
00034 
00052 template< typename T >
00053 class Output : public OutputNT 
00054 {
00055    public :
00056 
00063    Output( const Name & outputName, 
00064            SimulatedObject & owner,
00065            const int historySize,
00066            OMK::Type::PolatorNT * polator = 0 ) ;
00067 
00070    virtual ~Output() ;
00071 
00072 
00081    virtual const T& get( int & distanceToExactValue,
00082                          const int precisionLevel,
00083                          const Date & deltaT,
00084                          T& calculatedResult ) const ;
00085 
00086 
00089    virtual const T& getLastExactValue() const ;
00090 
00091    
00094    virtual const Date & getDateOfLastExactValue() const ;
00095 
00096 
00101    virtual void set( const T& newValue, bool alwaysUpdate = false ) ;
00102    
00103  
00107    virtual void suggest( const T& suggestedValue ) ;
00108 
00109 
00112    virtual T& getNextPlaceHolder() ;
00113 
00116    virtual void setInPlace( const T& ) ;
00117 
00118 
00121    virtual void connectedMyself( InputNT * input ) ;
00122 
00123 
00126    virtual void disconnectedMyself( InputNT * input ) ;
00127 
00128 
00132   
00135    virtual void extract( std::istream & = std::cin ) ;
00136 
00139    virtual void insertInStream( std::ostream & = std::cout ) const ;
00140 
00141 
00145    virtual void pack( OutgoingSynchronisationMessage & ) const ;
00146 
00147 
00151    virtual void packAllValues( OutgoingSynchronisationMessage & ) const ;
00152 
00153 
00157    virtual void unpack( IncomingSynchronisationMessage & ) ;
00158 
00162    virtual void unpackAllValues( IncomingSynchronisationMessage & ) ;
00164 
00165 
00169    virtual void printDebuggingInformation( std::ostream & err ) const ;
00170 
00173    void printHistory() const ;
00174 
00176    virtual void empty() ;
00177    
00181    virtual void setUsedOutput( Output< T > * output ) ;
00182 
00184    virtual void setAlias( OutputAlias< T > * output ) ;
00185 
00187    virtual void unsetAlias() ;
00188 
00190    virtual Output< T > * getUsedOutput() const ;
00191 
00192 
00194    virtual OutputAlias< T > * getAlias() const ;
00195 
00196 
00198 protected :
00202    virtual void setValidity( bool ) ;
00203 
00205    friend class OutputAlias< T > ;
00206 
00208    virtual const T& localGet( int & validiteRes,
00209                               const int niveauInterpol,
00210                               const Date & deltaT,
00211                               T& resultPlaceHolder ) const ;
00212 
00213 
00215    virtual void localInsert( std::ostream & = std::cout ) const ;
00216 
00218    OutputAlias< T > * _aliasOfOutput ;
00219    
00221    Output< T > * _usedOutput ;
00222  
00224    AbstractFifo < T > * _history ; 
00225 
00227    const Date & _date ;
00228 
00229 public:
00231   OMK::Type::Polator < T > * _polator;
00232 
00233 protected:
00235    std::list<Input < T > *> _listOfConnectedUnsensitiveInputs;
00236 
00240 #ifdef _OMK_MUTEX_
00241    OMKMutexLock _myMutex ;
00242 #endif
00243 
00245    bool _validity ;
00246 } ; // Output
00247 
00248 } // namespace OMK
00249 
00250 
00251 //-----------------------------------------------------------------------------
00252 //-----------------------------------------------------------------------------
00253 
00254 
00255 #include "OMKOutputAlias.h"
00256 
00257 namespace OMK
00258 {
00259 
00260 //-----------------------------------------------------------------------------
00261 
00262 template< typename T >
00263 inline Output< T >::Output( const Name & outputName,
00264                             SimulatedObject & owner,
00265                             const int historyLength,
00266                             OMK::Type::PolatorNT * polator )
00267   : KernelAttribute( owner, outputName ),
00268     OutputNT( owner, outputName ),
00269      _aliasOfOutput( 0 ),
00270      _date( owner.getController().getSimulatedDate() ),
00271      _validity( false )
00272 {
00273    /* Thread safety assessement : 
00274     * thread safe because only on construction of the object
00275     */
00276 
00277   if( polator == 0 )
00278   {
00279     // any type has a static method that creates a default polator
00280     T aTypeInstance ; // because createPolator isn't static
00281     _polator = static_cast< OMK::Type::Polator< T > * >(
00282       aTypeInstance.createPolator() ) ;
00283 
00284     if( _polator != 0 )
00285     {
00286       OMTRACEID( OMK_DEBUG_OMK_POL,
00287                  "Created default polator for output \""
00288                  << getName() << "\" of object \""
00289                  << owner.getName() << "\", with type "
00290                  << typeid( _polator ).name() ) ;
00291     }
00292     else
00293     {
00294       OMERROR( "Created default polator for output \""
00295                << getName() <<  "\" of object \""
00296                << owner.getName() << " is not of type \""
00297                << " OMK::Type::Polator <"
00298                << typeid( T ).name() << "> *\"" ) ;
00299     }
00300   }
00301   else 
00302   {
00303     _polator = dynamic_cast< OMK::Type::Polator< T > * >( polator ) ;
00304     if( _polator != 0)
00305     {
00306       OMTRACEID( OMK_DEBUG_OMK_POL,
00307                  "Given polator for output \""
00308                  << getName() << "\" of object \""
00309                  << owner.getName() << "\", with type "
00310                  << typeid( _polator ).name()
00311                  << " has been associated with this output" ) ;
00312     }
00313     else
00314     {
00315       OMERROR( "Created polator for output \""
00316                << getName() <<  "\" of object \""
00317                << owner.getName() << " is not of type \""
00318                << " OMK::Type::Polator <"
00319                << typeid( T ).name() << "> *\"" ) ;
00320     }
00321   }
00322   if( _polator == 0 )
00323   {
00324     OMFATALERROR( "No polator has been made for output \""
00325                   << getName() << "\" of object \""
00326                   << owner.getName() << "\"" ) ;
00327   }
00328 
00329   // calculate the appropriate history fifo length
00330   int realSize =
00331     historyLength + _polator->getNumberOfNeededValuesForMaxPrecisionPolation() ;
00332   _history = new Fifo< T >( realSize ) ;
00333   _polator->setFifo( _history ) ;
00334 
00335   _usedOutput = this ;
00336 }
00337 
00338 //-----------------------------------------------------------------------------
00339 
00340 template< typename T >
00341 inline Output< T >::~Output()
00342 {
00343   /* Thread safety assessement :
00344    * thread safe because only one destruction of the object
00345    */
00346 #ifdef _OMK_MUTEX_
00347   _myMutex.protect() ;
00348 #endif
00349 
00350   typename std::list< Input< T > * >::iterator j ;
00351   for( j = _listOfConnectedUnsensitiveInputs.begin() ;
00352        j != _listOfConnectedUnsensitiveInputs.end() ;
00353        j++ )
00354   {
00355     (*j)->outputDestroyed() ;
00356   }
00357 
00358 #ifdef _OMK_MUTEX_
00359   _myMutex.unprotect() ;
00360 #endif
00361 
00362   if( _aliasOfOutput != 0 )
00363   {
00364     _aliasOfOutput->aliasedOutputDeleted() ;
00365   }
00366   delete _history ;
00367 }
00368 
00369 //-----------------------------------------------------------------------------
00370 
00371 template <class T>
00372 inline void Output< T >::setUsedOutput( Output< T > * output )
00373 {
00374    /* Thread safety assessement :
00375     * multiple simultaneous access possible, and doesn't compromise thread
00376     * safety : last one out wins
00377     */
00378   _usedOutput = output ;
00379 }
00380 
00381 //-----------------------------------------------------------------------------
00382 
00383 template< typename T >
00384 inline void Output< T >::setValidity( bool b )
00385 {
00386   /* Thread safety assessement :
00387    * protected method, used to change protected member : thread safety should
00388    * be insured by callers 
00389    */
00390   _validity = b ;
00391 }
00392 
00393 //-----------------------------------------------------------------------------
00394 
00395 template< typename T > 
00396 inline void Output< T >::unsetAlias()
00397 {
00398   /* Thread safety assessement :
00399    * multiple simultaneous access possible, but they don't compromise thread
00400    * safety : last one out wins     
00401    */
00402   _aliasOfOutput = 0 ;
00403   setUsedOutput( this ) ;
00404 }
00405 
00406 //-----------------------------------------------------------------------------
00407 
00408 template< typename T > 
00409 inline void Output< T >::setAlias( OutputAlias< T > * output )
00410 {
00411    /* Thread safety assessement :
00412     * multiple simultaneous access possible, but they don't compromise thread
00413     * safety : last one out wins     
00414     */
00415   _aliasOfOutput = output ;
00416 }
00417 
00418 //-----------------------------------------------------------------------------
00419 
00420 template< typename T >
00421 inline Output< T > * Output< T >::getUsedOutput() const
00422 {
00423    /* Thread safety assessement :
00424     * protected method
00425     * multiple simultaneous access possible, but as long as this method is only
00426     * used onced by each access patern, the OMKOutput stays coherant   
00427     */
00428   return _usedOutput ;
00429 }
00430 
00431 //-----------------------------------------------------------------------------
00432 
00433 template< typename T >
00434 inline OutputAlias< T > * Output< T >::getAlias() const
00435 {
00436   /* Thread safety assessement :
00437    * protected method
00438    * multiple simultaneous access possible, but as long as this method is only
00439    * used onced by each access patern, the OMKOuptut stays coherant   
00440    */
00441   return _aliasOfOutput ;
00442 }
00443 
00444 //-----------------------------------------------------------------------------
00445 
00446 template< typename T >
00447 inline const T& Output< T >::get( int & validiteRes,
00448                                   const int niveauInterpol,
00449                                   const Date & deltaT,
00450                                   T& resultPlaceHolder ) const
00451 {
00452   /* Thread safety assessement :
00453    * As thread safe as localGet   
00454    */
00455 #ifdef _DEBUGTYPEUTIL
00456   std::cerr << "Output< T >::get" << std::endl ;
00457   std::cerr << "used Output: "<< getUsedOutpute() << std::endl ;
00458   std::cerr << "file: " << _history << std::endl ;
00459   _history->printDebuggingInformation() ;
00460   informations() ;
00461 #endif
00462    OMASSERT( getUsedOutput() != 0 ) ;
00463    return getUsedOutput()->localGet(
00464      validiteRes, niveauInterpol, deltaT, resultPlaceHolder ) ;
00465 }
00466 
00467 //-----------------------------------------------------------------------------
00468 
00469 template< typename T >
00470 const T& Output< T >::localGet( int & validiteRes,
00471                                 const int niveauInterpol,
00472                                 const Date & deltaT,
00473                                 T& resultPlaceHolder ) const
00474 {   
00475   /* Thread safety assessement :
00476    * As thread safe as polate from OMKInterplateur. But be careful : in a
00477    * multithreaded environment this member function can generate more
00478    * exceptions than expected 
00479    */
00480   touch() ;
00481   if( !_validity )
00482   {
00483     throw UnInitialisedOutputException( *this, "Output< T >::localGet \n" ) ;
00484   }
00485 
00486 #ifdef _DEBUGTYPEUTIL
00487   std::cerr << "Output< T >::localGet" << std::endl ;
00488   std::cerr << owner.getController().getSimulatedDate() << std::endl ;
00489   std::cerr << "Interpolateur : "<< _polator << std::endl ;
00490 #endif
00491   Date date = _owner.getController().getSimulatedDate() - deltaT ;
00492   return _polator->polate(
00493     niveauInterpol, date, validiteRes, resultPlaceHolder ) ;
00494 }
00495 
00496 //-----------------------------------------------------------------------------
00497 
00498 template< typename T >
00499 void Output< T >::connectedMyself( InputNT * input )
00500 {
00501   /* Thread safety assessement : 
00502    * Critical data is mutex protected  
00503    */
00504   touch() ;
00505 #ifdef _OMK_MUTEX_
00506   _myMutex.protect() ;
00507 #endif
00508 
00509   Input< T > * standardInput = dynamic_cast<Input< T > * >( input ) ;
00510   OMASSERT( standardInput != 0 ) ;
00511   _listOfConnectedUnsensitiveInputs.push_back( standardInput ) ;
00512 
00513 #ifdef _OMK_MUTEX_
00514   _myMutex.unprotect() ;
00515 #endif
00516 }
00517 
00518 //-----------------------------------------------------------------------------
00519 
00520 template< typename T >
00521 void Output< T >::disconnectedMyself( InputNT * input )
00522 {
00523 #ifdef _DEBUGALIAS
00524   std::cerr << "Output< T >::disconnectedMyself" << std::endl ;
00525 #endif
00526 
00527   /* Thread safety assessement :
00528    * critical data is mutex protected  
00529    */
00530 #ifdef _OMK_MUTEX_
00531   _myMutex.protect() ;
00532 #endif
00533 
00534   Input < T > * unsensitiveInput = dynamic_cast< Input < T > * >( input ) ;
00535   _listOfConnectedUnsensitiveInputs.remove( unsensitiveInput ) ;
00536 
00537 #ifdef _OMK_MUTEX_
00538   _myMutex.unprotect() ;
00539 #endif
00540 }
00541 
00542 //-----------------------------------------------------------------------------
00543 
00544 template< typename T >
00545 inline void Output< T >::set( const T& newValue,
00546                               bool alwaysUpdate /*= false*/ ) 
00547 {
00550 #ifndef NDEBUG
00551   if( CurrentActiveObject::getCurrentActiveObject() != &_owner
00552    && CurrentActiveObject::getCurrentActiveObject() != &_owner.getController()
00553    && CurrentActiveObject::getCurrentActiveObject() )
00554   {
00555     OMERROR( ":-( Error in Output<" << typeid( T ).name() 
00556              << ">::set:  Unable to set the output \""
00557              << getName().getString() << "\""
00558              << std::endl
00559              << "The output owner [" << _owner.getName()
00560              << "] is not the active object ["
00561              << ( CurrentActiveObject::getCurrentActiveObject() ? 
00562                   CurrentActiveObject::getCurrentActiveObject()->getName().getString() :
00563                   std::string( "no active object" ) )
00564              << "]" ) ;
00565   }
00566 #endif
00567 
00568   /*OMASSERT( &_owner == CurrentActiveObject::getCurrentActiveObject() 
00569             || CurrentActiveObject::getCurrentActiveObject() == & _owner.getController()
00570             || CurrentActiveObject::getCurrentActiveObject() == 0 ) ;*/
00571   /* Thread safety assessement :
00572    * localGet and set could collide. Thread safety can only be assured if the
00573    * fifo and the interpolator are thread safe with respect to the value in the
00574    * fifo.
00575    * Only one set at a time.
00576    */
00577   _history->set( newValue, _date ) ;
00578   setValidity( true ) ;
00579 }
00580 
00581 //-----------------------------------------------------------------------------
00582 
00583 template< typename T >
00584 inline void Output< T >::extract( std::istream & in )
00585 {
00586   /* Thread safety assessement :
00587    * localGet and extract could collide. Thread safety can only be assured if
00588    * the fifo and the interpolator are thread safe with respect to the values
00589    * in the fifo.
00590    * Only one extract at a time.
00591    */
00592   in >> *_history ;
00593   setValidity( true ) ;
00594 }
00595 
00596 //-----------------------------------------------------------------------------
00597 
00598 template< typename T >
00599 void Output< T >::pack( OutgoingSynchronisationMessage & out ) const
00600 {
00601   //std::cerr << "Output< T >::pack" << std::endl ;
00602   //packs the name of the output, then any usefull information
00603   /* Thread safety assement :
00604    * Thread safe : collides with set and localInsert on the AbstractFifo. But
00605    * they should only be activated by the owner. So as long as the owner isn't
00606    * multithreaded...
00607    * Nota : in a multithreaded environment this member function could generate
00608    * more exceptions than expected
00609    */
00610   if( _validity && out.getMessageDate() == _history->getPreceedingDate( 0 ) )
00611   {
00612     getName().pack( out ) ;
00613     _history->pack( out ) ;
00614   }
00615   //else : do not pack anything, therefore mirror will remain uninitialised
00616   //std::cerr << "Output< T >:" << this << ":pack done" << std::endl ;
00617 }
00618 
00619 //-----------------------------------------------------------------------------
00620 
00621 template< typename T >
00622 void Output< T >::packAllValues( OutgoingSynchronisationMessage & out ) const
00623 {
00624   //std::cerr<<"packAllValues output \"" << getName() << "\"" ) ;
00625   //packs the name of the output, then all initial information
00626   /* Thread safety assement :
00627    * Thread safe : collides with set and localInsert on the AbstractFifo. But
00628    * they should only be activated by the owner. So as long as the owner isn't
00629    * multithreaded, or that the kernel doesn't call this member function during
00630    * activation of the owner...
00631    * Nota : in a multithreaded environment this member function could generate
00632    * more exceptions than expected
00633    */
00634   if( _validity )
00635   {
00636     getName().pack( out ) ;
00637     _history->packAllValues( out ) ;
00638   }
00639   //else : do not pack anything, therefore mirror will remain uninitialised
00640   //std::cerr<<"Output< T >:" << this << ":packAllValues done" << std::endl ;
00641 }
00642 
00643 //-----------------------------------------------------------------------------
00644 
00645 template< typename T >
00646 void Output< T >::unpack( IncomingSynchronisationMessage & in )
00647 {
00648   // shouldn't unpack the name, but all other usefull information packed
00649   /* Thread safety assessement : 
00650    * localGet and extract could collide. Thread safety can only be assured if
00651    * the fifo and the interpolator are thread safe with respect to the values
00652    * in the fifo.
00653    * Only one extract at a time.
00654    */
00655   _history->unpack( in ) ;
00656   setValidity( true ) ;
00657 }
00658 
00659 //-----------------------------------------------------------------------------
00660 
00661 template< typename T >
00662 void Output< T >::unpackAllValues( IncomingSynchronisationMessage & in )
00663 {
00664   // shouldn't unpack the name, but all other usefull information packed
00665   /* Thread safety assessement : 
00666    * localGet and extract could collide. Thread safety can only be assured if
00667    * the fifo and the interpolator are thread safe with respect to the values
00668    * in the fifo.
00669    * Only one extract at a time.
00670    */
00671   _history->unpackAllValues( in ) ;
00672   setValidity( true ) ;
00673 }
00674 
00675 //-----------------------------------------------------------------------------
00676 
00677 template< typename T >
00678 inline void Output< T >::insertInStream( std::ostream & out ) const
00679 {
00680   /* Thread safety assessement :
00681    * As thread safe as localInsert 
00682    */
00683   getUsedOutput()->localInsert( out ) ; 
00684 }
00685 
00686 //-----------------------------------------------------------------------------
00687 
00688 template< typename T >
00689 inline void Output< T >::localInsert( std::ostream & out ) const
00690 {
00691   /* Thread safety assement
00692    * Thread safe : collides with set on the AbstractFifo. But they should only
00693    * be activated by the owner. So as lmong as the owner isn't multithreaded...
00694    * Nota : in a multithreaded environment this member function could generate
00695    * more exceptions than expected
00696    */
00697   if( !_validity )
00698   {
00699     UnInitialisedOutputException exception( *this,
00700                                             "Output< T >::localInsert\n" ) ;
00701     exception << "Cannot read uninitailised output of "
00702               << _owner.getName().getCString() ;
00703     throw exception ;
00704   }
00705   else 
00706   {
00707     out << *_history << " " ;
00708   }
00709 }
00710 
00711 //-----------------------------------------------------------------------------
00712 
00713 template< typename T >
00714 inline void Output< T >::printHistory() const
00715 {
00716   /* thread safety assessement :
00717    * const method : should be thread safe if printDebuggingInformation of
00718    * AbstractFifo is thread safe
00719    */
00720   _history->printDebuggingInformation() ;
00721 }
00722 
00723 //-----------------------------------------------------------------------------
00724 
00725 template< typename T >
00726 inline void Output< T >::printDebuggingInformation( std::ostream & err ) const
00727 {
00728    /* thread safety assessement :
00729     * const method : thread safe. shown value may not be a coherant image of
00730     * an Output
00731     */
00732   err << std::endl
00733       << "**********************************************************"
00734       << std::endl
00735       << "Class Output" << std::endl
00736       << "Owner : " << _owner.getName() << std::endl
00737       << "Output Name : "<< _name << std::endl
00738       << "T of output : "<< typeid( T ).name() << std::endl 
00739       << "Output primary alias : " << getAlias() << std::endl 
00740       << "Used Output : " << getUsedOutput() << std::endl 
00741       << "History Fifo: " << _history << std::endl ;
00742 }
00743 
00744 //-----------------------------------------------------------------------------
00745 
00746 template< typename T >
00747 inline void Output< T >::empty()
00748 {
00749   /* Thread safety assessement :
00750    * as thread safe as clear of fifo. Only one simultaneous acces possible (in
00751    * theory).
00752    */
00753   _history->clear() ;
00754   setValidity( false ) ;
00755 }
00756 
00757 //-----------------------------------------------------------------------------
00758 
00759 template< typename T >
00760 inline const T& Output< T >::getLastExactValue() const
00761 {
00762   touch() ;
00763   // this bypasses any Polator
00764   if( _history->getNumberOfPresentValues( 1 ) < 1 ) // if no value is stored
00765   {
00766     UnInitialisedOutputException exception(
00767       *this, "Output< T >::getLastExactValue\n" ) ;
00768     exception << "Impossible to get a value from an uninitialised output of "
00769               << _owner.getName().getCString() ;
00770     throw exception ;
00771   }
00772   return _history->getPreceedingValue( 0 ) ;
00773 }
00774 
00775 //-----------------------------------------------------------------------------
00776 
00777 template< typename T >
00778 inline const Date & Output< T >::getDateOfLastExactValue() const
00779 {
00780    touch() ;
00781    // this bypasses any Polator
00782    if( _history->getNumberOfPresentValues( 1 ) < 1 ) // if no value is stored
00783    {
00784      UnInitialisedOutputException exception(
00785        *this, "Output< T >::getLastExactValue\n" ) ;
00786      exception << "Impossible to get a value from an uninitialised output of "
00787                << _owner.getName().getCString() ;
00788      throw exception ;
00789    }
00790    return _history->getPreceedingDate( 0 ) ;
00791 }
00792 
00793 //-----------------------------------------------------------------------------
00794 
00795 template< typename T >
00796 inline T& Output< T >::getNextPlaceHolder()
00797 {
00798   return _history->getNextPlaceHolder() ;
00799 }
00800 
00801 //-----------------------------------------------------------------------------
00802 
00803 template< typename T >
00804 inline void Output< T >::setInPlace( const T& newValue )
00805 {
00806   _history->setInPlace( newValue, _date ) ;
00807   setValidity( true ) ;
00808 }
00809 
00810 //-----------------------------------------------------------------------------
00811 
00812 template< typename T >
00813 inline void Output< T >::suggest( const T& newValue )
00814 {
00815   if( !_validity )
00816   {
00817     _history->set( newValue , _owner.getController().getSimulatedDate() ) ;
00818     setValidity( true ) ;
00819   }
00820 }
00821 
00822 //-----------------------------------------------------------------------------
00823 
00824 } // namespace OMK
00825 
00826 #endif

logo OpenMask

Documentation generated on Mon Jun 9 11:45:57 2008

Generated with doxygen by Dimitri van Heesch ,   1997-2007