OMKObjectDescriptor.cpp

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 #include "OMKObjectDescriptor.h"
00019 #include "OMKCurrentActiveObject.h"
00020 #include "OMKMultipleConfigurationParameter.h"
00021 #include "OMKSimulatedObject.h"
00022 #include "OMKSimpleTypeT.inl"
00023 #include "OMKUniqueConfigurationParameter.h"
00024 #include "OMKUserException.h"
00025 
00026 #include "OMKtokens.h"
00027 #include "OMKgenericKernelParser.h"
00028 #include "OMKKernelIstreamLexer.h"
00029 #include "OMKTracer.h"
00030 
00031 using namespace OMK ;
00032 //------------------------------------------------------------------------------
00033 ObjectDescriptor::ObjectDescriptor()
00034   : _pointerToSimulatedObject( 0 ),
00035     _destroySimulatedObject( false ),
00036     _configurationParameters( 0 ),
00037     _extensionsParameters( 0 ),
00038     _originalSchedulingParameters( 0 ),
00039     _schedulingParameters( 0 ),
00040     _fathersDescription( 0 ),
00041     _creatingObject( false ),
00042 #ifndef _MSC_VER
00043     _creatingThread( 0 ),
00044 #endif
00045     _frequency( 0 ),
00046     _distribution( DEFAULT_OBJECT ),
00047     _originalFrequency( 0 )
00048 {
00049   // otherwise, the initial value of _creatingThread is inappropriate
00050 #if !defined _MSC_VER && defined _OMK_MUTEX_
00051   OMASSERT( pthread_self() != 0 ) ;
00052 #endif
00053 }
00054 //------------------------------------------------------------------------------
00055 ObjectDescriptor::ObjectDescriptor( const ObjectDescriptor & orig )
00056   : _pointerToSimulatedObject( 0 ),
00057     _destroySimulatedObject( false ),
00058     _objectName( orig._objectName ),
00059     _classId( orig._classId ),
00060     _configurationParameters( 0 ),
00061     _extensionsParameters( 0 ),
00062     _originalSchedulingParameters( 0 ),
00063     _schedulingParameters( 0 ),
00064     _fathersDescription( 0 ),
00065     _creatingObject( false ),
00066     _processId( orig._processId ),
00067     _frequency( orig._frequency ),
00068     _distribution( orig._distribution ),
00069     _originalFrequency( orig._originalFrequency )
00070 {
00071   _configurationParameters =
00072     orig._configurationParameters != 0 ?
00073     orig._configurationParameters->clone() : 0 ;
00074 
00075   _extensionsParameters =
00076     orig._extensionsParameters != 0 ?
00077     orig._extensionsParameters->clone() : 0 ;
00078 
00079   _originalSchedulingParameters =
00080     orig._originalSchedulingParameters != 0 ?
00081     static_cast< MultipleConfigurationParameter *>(
00082       orig._originalSchedulingParameters->clone() ) : 0 ;
00083 
00084   _schedulingParameters =
00085     orig._schedulingParameters != 0 ?
00086     static_cast< MultipleConfigurationParameter *>(
00087       orig._schedulingParameters->clone() ) : 0 ;
00088 
00089   // Only one descriptor by object. Assume descriptor is copied only before
00090   // the described object is created
00091   OMASSERT( orig._pointerToSimulatedObject == 0 ) ;
00092   OMASSERT( orig._destroySimulatedObject == false ) ;
00093 
00094   // copy the sons
00095   for( SonsContainerType::const_iterator i = orig._sonsContainer.begin() ;
00096        i != orig. _sonsContainer.end() ;
00097        ++i )
00098   {
00099     addSon( new ObjectDescriptor( *( *i ) ) ) ;
00100   }
00101 }
00102 //------------------------------------------------------------------------------
00103 ObjectDescriptor::ObjectDescriptor(
00104   const Name & objectName,
00105   const Name & classId,
00106   const Name & processId,
00107   const Frequency & frequency,
00108   ConfigurationParameterDescriptor * configurationParameters,
00109   ConfigurationParameterDescriptor * extensionsParameters,
00110   Distribution distribution )
00111   : _pointerToSimulatedObject( 0 ),
00112     _destroySimulatedObject( false ),
00113     _objectName( objectName ),
00114     _classId( classId ),
00115     _configurationParameters( configurationParameters ),
00116     _extensionsParameters( extensionsParameters ),
00117     _originalSchedulingParameters( 0 ),
00118     _schedulingParameters( 0 ),
00119     _fathersDescription( 0 ),
00120     _creatingObject( false ),
00121 #ifndef _MSC_VER
00122     _creatingThread( 0 ),
00123 #endif
00124     _processId( processId ),
00125     _frequency( frequency ),
00126     _distribution( distribution ),
00127     _originalFrequency( frequency )
00128 {
00129 #if !defined _MSC_VER && defined _OMK_MUTEX_
00130   OMASSERT( pthread_self() != 0 ) ;
00131 #endif
00132   _schedulingParameters = new MultipleConfigurationParameter() ;
00133   std::ostringstream freq ;
00134   freq << frequency ;
00135   _schedulingParameters->appendSubDescriptorNamed(
00136     "Frequency",
00137     new UniqueConfigurationParameter( freq.str() ) ) ;
00138   _schedulingParameters->appendSubDescriptorNamed(
00139     "Process",
00140     new UniqueConfigurationParameter( processId.getString() ) ) ;
00141   _originalSchedulingParameters = static_cast< MultipleConfigurationParameter *>(
00142     _schedulingParameters->clone() ) ;
00143 }
00144 //------------------------------------------------------------------------------
00145 ObjectDescriptor::ObjectDescriptor(
00146   const Name & objectName,
00147   const Name & classId,
00148   const Frequency & frequency,
00149   ConfigurationParameterDescriptor * configurationParameters,
00150   ConfigurationParameterDescriptor * extensionsParameters,
00151   Distribution distribution )
00152   : _pointerToSimulatedObject( 0 ),
00153     _destroySimulatedObject( false ),
00154     _objectName( objectName ),
00155     _classId( classId ),
00156     _configurationParameters( configurationParameters ),
00157     _extensionsParameters( extensionsParameters ),
00158     _originalSchedulingParameters( 0 ),
00159     _schedulingParameters( 0 ),
00160     _fathersDescription( 0 ),
00161     _creatingObject( false ),
00162 #ifndef _MSC_VER
00163     _creatingThread( 0 ),
00164 #endif
00165     _frequency( frequency ),
00166     _distribution( distribution ),
00167     _originalFrequency( frequency )
00168 {
00169 #if !defined _MSC_VER && defined _OMK_MUTEX_
00170   OMASSERT( pthread_self() != 0 ) ;
00171 #endif
00172 
00173   _schedulingParameters = new MultipleConfigurationParameter() ;
00174   std::ostringstream freq ;
00175   freq << frequency ;
00176   _schedulingParameters->appendSubDescriptorNamed(
00177     "Frequency", 
00178     new UniqueConfigurationParameter( freq.str() ) ) ;
00179   _originalSchedulingParameters = static_cast< MultipleConfigurationParameter *>(
00180     _schedulingParameters->clone() ) ;
00181 }
00182 //------------------------------------------------------------------------------
00183 ObjectDescriptor::ObjectDescriptor(
00184   const Name & objectName,
00185   const Name & classId,
00186   MultipleConfigurationParameter * schedulingParameters,
00187   ConfigurationParameterDescriptor * configurationParameters,
00188   ConfigurationParameterDescriptor * extensionsParameters )
00189   : _pointerToSimulatedObject( 0 ),
00190     _destroySimulatedObject( false ),
00191     _objectName( objectName ),
00192     _classId( classId ),
00193     _configurationParameters( configurationParameters ),
00194     _extensionsParameters( extensionsParameters ),
00195     _originalSchedulingParameters( 0 ),
00196     _schedulingParameters( schedulingParameters ),
00197     _fathersDescription( 0 ),
00198     _creatingObject( false )
00199 #if !defined _MSC_VER && defined _OMK_MUTEX_
00200     ,_creatingThread( 0 )
00201 #endif
00202 {
00203 #if !defined _MSC_VER && defined _OMK_MUTEX_
00204   OMASSERT( pthread_self() != 0 ) ;
00205 #endif
00206 
00207   interpretSchedulingParameters( schedulingParameters ) ;
00208 }
00209 //------------------------------------------------------------------------------
00210 ObjectDescriptor::~ObjectDescriptor() 
00211 {
00212   if( _destroySimulatedObject )
00213   {
00214     if( _pointerToSimulatedObject == 0 )
00215     {
00216       OMERROR( "ObjectDescriptor::~ObjectDescriptor() destroying "
00217                << getName() << " in incooherant state" << std::endl ) ;
00218     }
00219     delete _pointerToSimulatedObject ;
00220   }
00221 
00222   if( _fathersDescription != 0 )
00223   {
00224     _fathersDescription->removeSon( this ) ;
00225   }
00226 
00227   delete _originalSchedulingParameters ;
00228   delete _schedulingParameters ;
00229   delete _configurationParameters ;
00230   delete _extensionsParameters ;
00231 
00232   if( !_sonsContainer.empty() )
00233   {
00234     OMTRACEID( OMK_DEBUG_OMK_OBJ, "ObjectDescriptor with "
00235                << _sonsContainer.size()
00236                << " remaining sons deleted. Sons not deleted" << std::endl ) ;
00237   }
00238 }
00239 //------------------------------------------------------------------------------
00240 
00241 ConfigurationParameterDescriptor * ObjectDescriptor::getConfigurationParameters(
00242   bool create )
00243 {
00244   if( create && !_configurationParameters )
00245   {
00246     _configurationParameters = new MultipleConfigurationParameter() ;
00247   }
00248   return _configurationParameters ;
00249 }
00250 //------------------------------------------------------------------------------
00251 ConfigurationParameterDescriptor * ObjectDescriptor::getExtensionsParameters(
00252   bool create )
00253 {
00254   if( create && !_extensionsParameters )
00255   {
00256     _extensionsParameters = new MultipleConfigurationParameter() ;
00257   }
00258   return _extensionsParameters ;
00259 }
00260 //------------------------------------------------------------------------------
00261 void ObjectDescriptor::unpack( IncomingSynchronisationMessage & in )
00262 {
00263   std::string messageBuffer ;
00264   in >> messageBuffer ;
00265   std::istringstream message( messageBuffer );
00266   extract(message ) ;
00267 }
00268 //------------------------------------------------------------------------------
00269 void ObjectDescriptor::pack( OutgoingSynchronisationMessage & out ) const
00270 {
00271   // packed in a quite inefficient way (unsing the string representation of the
00272   // object descriptor), 
00273   // but much simpler to decode : therefore, use extract
00274   std::ostringstream char_out ;
00275   printToStream( char_out, 0 ) ;
00276   out << char_out.str() ;
00277 }
00278 //------------------------------------------------------------------------------
00279 void ObjectDescriptor::extract( std::istream & in )
00280 {
00281   _sonsContainer.clear() ;
00282    
00283   KernelIstreamLexer< std::istream > inputStream( in ) ;
00284   DLGLexer scan( & inputStream ) ;
00285   ANTLRTokenBuffer pipe( & scan ) ;
00286   ANTLRTokenPtr aToken = new ANTLRToken() ;
00287   scan.setToken( mytoken( aToken ) ) ;
00288   genericKernelParser extractor( &pipe ) ;
00289   extractor.init() ;
00290 
00291   std::string stringName;
00292   extractor.key( stringName ) ;
00293   _objectName = stringName ;
00294 
00295   ConfigurationParameterDescriptor *genericSubDescription =
00296     extractor.anonymousValue() ;
00297   MultipleConfigurationParameter * generalDescription =
00298     dynamic_cast< MultipleConfigurationParameter * >( genericSubDescription );
00299   if( generalDescription == 0 )
00300   {
00301     throw UserException( "Unable to extract a name for an ObjectDescriptor from a stream" ) ;
00302   }
00303 
00304   genericSubDescription = generalDescription->getSubDescriptorByName( "Class" ) ;
00305   if( genericSubDescription == 0 ) 
00306   {
00307     throw UserException( "Unable to extract a class for an ObjectDescriptor from a stream") ;
00308   }
00309   _classId = genericSubDescription->getAssociatedString() ;
00310 
00311   delete _configurationParameters ;
00312   _configurationParameters =
00313     generalDescription->getSubDescriptorByName( "UserParams" ) ;
00314 
00315   delete _extensionsParameters ;
00316   _extensionsParameters =
00317     generalDescription->getSubDescriptorByName( "Extensions" ) ;
00318 
00319   genericSubDescription =
00320     generalDescription->getSubDescriptorByName( "Scheduling" ) ;
00321   if( genericSubDescription !=0 )
00322   {
00323     interpretSchedulingParameters(
00324       dynamic_cast< MultipleConfigurationParameter * >( genericSubDescription ) ) ;
00325   }
00326   else
00327   {
00328     interpretSchedulingParameters( 0 ) ;
00329   }
00330 
00331   genericSubDescription = generalDescription->getSubDescriptorByName( "Sons" ) ;
00332   generalDescription =
00333     dynamic_cast< MultipleConfigurationParameter * >( genericSubDescription ) ;
00334   if( generalDescription != 0 )
00335   {
00336     interpretConfigurationParameterAsListOfSons( _sonsContainer, generalDescription ) ;
00337   }
00338 }
00339 //------------------------------------------------------------------------------
00340 void ObjectDescriptor::printToStream( std::ostream & out, int offset ) const
00341 {
00342   //suppose any needed offset has allready been printed
00343   out << getName() << std::endl ;
00344   printTabToStream( out,offset + 2 ) ;
00345   out << "{" << std::endl ;
00346   printTabToStream( out, offset + 4 ) ;
00347   out << "Class " << getClass() << std::endl ;
00348   if( getSchedulingParameters() != 0 )
00349   {
00350     printTabToStream( out, offset + 4 ) ;
00351     out << "Scheduling " ;
00352     getSchedulingParameters()->printToStream( out, offset + 6 ) ;
00353     out << std::endl ;
00354   }
00355   if( getConfigurationParameters() != 0 )
00356   {
00357     printTabToStream( out, offset + 4 ) ;
00358     out << "UserParams " ;
00359     getConfigurationParameters()->printToStream( out, offset + 6 ) ;
00360     out << std::endl ;
00361   }
00362   if( getExtensionsParameters() != 0 )
00363   {
00364     printTabToStream( out, offset + 4 ) ;
00365     out << "Extensions " ;
00366     getExtensionsParameters()->printToStream( out, offset + 6 ) ;
00367     out << std::endl ;
00368   }
00369   if( _sonsContainer.size() != 0 )
00370   {
00371     printTabToStream( out, offset + 4 ) ;
00372     out << "Sons" << std::endl ;
00373     printTabToStream( out, offset + 6 ) ;
00374     out << "{" << std::endl ;
00375     for( SonsContainerType::const_iterator i = _sonsContainer.begin() ;
00376          i != _sonsContainer.end() ;
00377          ++i )
00378     {
00379       printTabToStream( out, offset + 8 ) ;
00380       ( *i )->printToStream( out, offset + 8 ) ;
00381     }
00382     printTabToStream( out, offset + 6 ) ;
00383     out << "}" << std::endl ; 
00384   }
00385   printTabToStream( out, offset + 2 ) ;
00386   out << "}" << std::endl ;
00387 }
00388 //------------------------------------------------------------------------------
00389 void ObjectDescriptor::insertInStream( std::ostream & out ) const 
00390 {
00391   printToStream( out, 0 ) ;
00392 } 
00393 //------------------------------------------------------------------------------
00394 void ObjectDescriptor::setProcess( const Name & newProcessName )
00395 {
00396   _processId = newProcessName ;
00397   UniqueConfigurationParameter * description =
00398     dynamic_cast< UniqueConfigurationParameter * >(
00399       _schedulingParameters->getSubDescriptorByName( "Process" ) );
00400   if( description != 0 )
00401   {
00402     description->changeConfigurationParameter( newProcessName.getCString() ) ;
00403   }
00404   else
00405   {
00406     _schedulingParameters->appendSubDescriptorNamed(
00407       "Process", 
00408       new UniqueConfigurationParameter( newProcessName.getCString() ) ) ;
00409   }
00410 }
00411 //------------------------------------------------------------------------------
00412 void ObjectDescriptor::setFrequency( const Frequency & newFrequency ) 
00413 {
00414   _frequency = newFrequency ;
00415    
00416   UniqueConfigurationParameter *description =
00417     dynamic_cast< UniqueConfigurationParameter * >(
00418       _schedulingParameters->getSubDescriptorByName( "Frequency" ) );
00419   if( description != 0 )
00420   {
00421     std::ostringstream freq ;
00422     freq << newFrequency ;
00423     description->changeConfigurationParameter( freq.str() ) ;
00424   }
00425   else
00426   {
00427     std::ostringstream freq ;
00428     freq << newFrequency ;
00429     _schedulingParameters->appendSubDescriptorNamed(
00430       "Frequency",
00431       new UniqueConfigurationParameter( freq.str() ) ) ;
00432   }
00433 }
00434 //------------------------------------------------------------------------------
00435 void ObjectDescriptor::setDistribution( Distribution newDistribution )
00436 {
00437   _distribution = newDistribution ;
00438    UniqueConfigurationParameter *description =
00439      dynamic_cast< UniqueConfigurationParameter * >(
00440        _schedulingParameters->getSubDescriptorByName( "Distribution" ) ) ;
00441    if( description != 0 )
00442    {
00443      description->changeConfigurationParameter(
00444        ( newDistribution == DUPLICATED_OBJECT ) ? "Duplicated" :
00445        ( ( newDistribution == LOCAL_OBJECT ) ? "Local" : "Default" ) ) ;
00446    }
00447    else
00448    {
00449      _schedulingParameters->appendSubDescriptorNamed(
00450        "Distribution", 
00451        new UniqueConfigurationParameter(
00452          ( newDistribution == DUPLICATED_OBJECT ) ? "Duplicated" :
00453          ( ( newDistribution == LOCAL_OBJECT ) ? "Local" : "Default" ) ) ) ;
00454    }
00455 }
00456 //------------------------------------------------------------------------------
00457 void ObjectDescriptor::interpretSchedulingParameters(
00458   MultipleConfigurationParameter *schedulingParameters )
00459 {
00460   if( _schedulingParameters != schedulingParameters )
00461   {
00462     delete _schedulingParameters ;
00463   }
00464 
00465   _schedulingParameters = schedulingParameters ;    
00466   if( _schedulingParameters == 0 )
00467   {
00468     _schedulingParameters = new MultipleConfigurationParameter() ;
00469   } 
00470 
00471   const ConfigurationParameterDescriptor *description =
00472     _schedulingParameters->getSubDescriptorByName( "Frequency" ) ;
00473   if( description != 0 )
00474   {
00475     std::istringstream strValue( description->getAssociatedString() ) ;
00476     strValue >> _frequency ;
00477   }
00478   else
00479   {
00480     _frequency = 0 ;
00481     _schedulingParameters->appendSubDescriptorNamed(
00482       "Frequency",
00483       new UniqueConfigurationParameter( "0" ) ) ;
00484   }
00485 
00486   delete _originalSchedulingParameters ;
00487 
00488   _originalSchedulingParameters =
00489     static_cast< MultipleConfigurationParameter *>(
00490       _schedulingParameters->clone() ) ;
00491 
00492   _originalFrequency = _frequency ;
00493 
00494   description = _schedulingParameters->getSubDescriptorByName( "Process" ) ; 
00495   if( description != 0 )
00496   {
00497     _processId = description->getAssociatedString() ;
00498   }
00499   else
00500   {
00501     OMTRACEID( OMK_DEBUG_PVM, "No Process parameter for OSO" << _objectName );
00502   }
00503 
00504   _distribution = DEFAULT_OBJECT ;
00505   description = _schedulingParameters->getSubDescriptorByName( "Distribution" ) ;
00506   if( description != 0 )
00507   {
00508     std::string value( description->getAssociatedString() ) ;
00509     if( value == "Local" )
00510     {
00511       _distribution = LOCAL_OBJECT ;
00512     }
00513     else if( value == "Duplicated" )
00514     {
00515       _distribution = DUPLICATED_OBJECT ;
00516     }
00517   }
00518 }
00519 //------------------------------------------------------------------------------
00520 void ObjectDescriptor::setFathersDescription( ObjectDescriptor *newFather )
00521 {
00522   OMASSERT( newFather != 0 ) ;
00523   if( _fathersDescription != 0 )
00524   {
00525     _fathersDescription->removeSon( this ) ;
00526   }
00527 
00528   if( newFather->findDescendantNamed( getName() ) != 0 )
00529   {
00530     //cannot add the object : do nothing
00531     OMTRACEID( OMK_DEBUG_OMK_OBJ,
00532                "ObjectDescriptor::setFathersDescription of object named \""
00533                << getName()
00534                << "\" failed because descendant with the same name allready exists for object named \""
00535                << newFather->getName() << "\"" );
00536   }
00537   else 
00538   {
00539     newFather->addSon( this ) ;
00540   }
00541 }
00542 //------------------------------------------------------------------------------
00543 SimulatedObject * ObjectDescriptor::createDescribedObject() const
00544 {
00545 #if !defined _MSC_VER && defined _OMK_MUTEX_
00546   //here, use mutual exclusion, to avoid
00547   // 1 - recursive creation loops
00548   // 2 - simultaneous creations
00549   // 3 - recursive creation loops during simultaneous creations!
00550   //therefore, only allow one thread to do creation at a time (share the
00551   // creatingThread exclusion lock, and test to see if we're in a recursive loop)
00552 
00553   _dataLock.protect() ;
00554 
00555   SimulatedObject *result( _pointerToSimulatedObject ) ;
00556 
00557   if( _pointerToSimulatedObject == 0 )
00558   {
00559     if( _creatingObject && ( _creatingThread == pthread_self() ) )
00560     {
00561       // recursive creation loop : return null is the best that can be done
00562       _dataLock.unprotect() ;
00563     }
00564     else
00565     {
00566       // the object needs creating : here the question is whether an other
00567       // thread is creating it or not
00568       if( _creatingObject )
00569       {
00570         //other thread is creating the object : wait for it to finish creation
00571         _createdCondition.waitForChange( _dataLock ) ;
00572       }
00573       else 
00574       {
00575         //no thread is creating the object, 
00576         //therefore this thread takes responsability for creation
00577         _creatingObject = true ;
00578         _creatingThread = pthread_self() ;
00579         _dataLock.unprotect() ;
00580 
00581         //here, we can garantie that we are the only creating thread,
00582         //and that 
00583         // 1 - any recursive creation loop is a non-blocking creation
00584         // 2 - other threads creating the object are waiting on the condition
00585 
00586         //attempt object creation
00587         SimulatedObject *father( 0 ) ;
00588         const ObjectDescriptor *fathersDescription( _fathersDescription ) ;
00589 
00590         // as creation can happen during a paralel simulation,
00591         // it can happen at a time where getCurrentActiveObject returns the
00592         // object whose request triggered instance creation.
00593         // Therefore, the current active object is temporarly set to null,
00594         // so as to mimic creation phase.
00595         // If it is set to the controller, changing a controlparameter
00596         // triggers the sending of a valueEvent by the controller, which
00597         // might not have it's objectHandle initialized in order to avoid
00598         // being scheduled by itself
00599         CurrentActiveObject context( 0 ) ;
00600          
00601         while( fathersDescription != 0 )
00602         {
00603           father = fathersDescription->createDescribedObject() ;
00604           if( father != 0 )
00605           {
00606             OMTRACEID( OMK_DEBUG_OMK_OBJ,
00607                        "Creating object of type \"" << getClass() << "\"" ) ;
00608             SimulatedObject *result(
00609               SimulatedObjectFactory::getInstance().create( getClass() )(
00610                 father->getController() , *this ) ) ;
00611             OMTRACEID( OMK_DEBUG_OMK_OBJ,
00612                        "Creating object of type \"" << getClass() << "\" done" ) ;
00613 
00614             //result = father -> createInstanceOfEncapsulatedClass( *this );
00615             _dataLock.protect() ;
00616             _pointerToSimulatedObject = result ;
00617             _dataLock.unprotect() ;
00618             if( _pointerToSimulatedObject != 0 )
00619             {
00620               _destroySimulatedObject = true ;
00621               fathersDescription = 0 ;
00622             }
00623             else 
00624             {
00625               fathersDescription = fathersDescription->getFathersObjectDescriptor() ;
00626             }
00627           }
00628           else 
00629           {
00630             fathersDescription = 0 ;
00631           }
00632         }
00633       }
00634       if( _pointerToSimulatedObject == 0 )
00635       {
00636         OMTRACEID( OMK_DEBUG_OMK_OBJ,
00637                    "ObjectDescriptor::createDescribedObject: unable to create \""
00638                    << getName() << "\" of class " << getClass() ) ;
00639       }
00640       _dataLock.protect() ;
00641       _creatingObject = false ;
00642       _creatingThread = 0 ;
00643       _dataLock.unprotect() ;
00644       //wathever the result, unblock other waiting threads
00645       _createdCondition.signalChange() ;
00646     }
00647   }
00648   else
00649   {
00650     _dataLock.unprotect() ;
00651   }
00652   return result ;
00653 
00654 #else // _MSC_VER || ! _OMK_MUTEX_
00655   SimulatedObject *result( _pointerToSimulatedObject ) ;
00656   if( _pointerToSimulatedObject == 0 )
00657   {
00658     //no thread is creating the object, 
00659     _creatingObject = true ;
00660          
00661     //here, we can garantie that we are the only creating thread,
00662     //and that 
00663     // 1 - any recursive creation loop is a non-blocking creation
00664     // 2 - other threads creating the object are waiting on the condition
00665 
00666     //attempt object creation
00667     SimulatedObject *father( 0 ) ;
00668     const ObjectDescriptor *fathersDescription( _fathersDescription ) ;
00669          
00670     // as creation can happen during a paralel simulation, (not here : no multi
00671     // threading in MSC version) it can happen at a time where
00672     // getCurrentActiveObject returns the object whose request triggered
00673     // instance creation.
00674     // Therefore, the current active object is temporarly set to null, so as to
00675     // mimic creation phase. If it is set to the controller, changing a
00676     // controlparameter triggers the sending of a valueEvent by the controller,
00677     // which might not have it's objectHandle initialized in order to avoid
00678     // being scheduled by itself
00679     
00680     while( fathersDescription != 0 )
00681     {
00682       father = fathersDescription->createDescribedObject() ;
00683       if( father != 0 )
00684       {
00685         OMTRACEID( OMK_DEBUG_OMK_OBJ, "Creating object of type \""
00686                    << getClass() << "\"" ) ;
00687         result = OMK::SimulatedObjectFactory::getInstance().create(
00688           getClass() )( father->getController() , *this ) ;
00689         OMTRACEID( OMK_DEBUG_OMK_OBJ,
00690                    "Creating object of type \"" << getClass()
00691                    << "\" done " << result ) ;
00692         //result = father -> createInstanceOfEncapsulatedClass (*this);
00693         _pointerToSimulatedObject = result ;
00694         if( _pointerToSimulatedObject != 0 )
00695         {
00696           _destroySimulatedObject = true ;
00697           fathersDescription = 0 ;
00698         }
00699         else 
00700         {
00701           fathersDescription = fathersDescription->getFathersObjectDescriptor() ;
00702         }
00703       }
00704       else 
00705       {
00706         fathersDescription = 0 ;
00707       }
00708     }
00709   }
00710 
00711   if( _pointerToSimulatedObject == 0 )
00712   {
00713     OMTRACEID( OMK_DEBUG_OMK_OBJ,
00714                "ObjectDescriptor::createDescribedObject: unable to create \""
00715                << getName() << "\" of class " << getClass() ) ;
00716   }
00717   _creatingObject = false ;
00718 
00719   return result ;
00720 
00721 #endif // _MSC_VER
00722 }
00723 //------------------------------------------------------------------------------
00724 void ObjectDescriptor::deleteCachedData()
00725 {
00726   if( _destroySimulatedObject )
00727   {
00728     OMASSERT( _pointerToSimulatedObject != 0 ) ;
00729     delete _pointerToSimulatedObject ;
00730     _pointerToSimulatedObject = 0 ;
00731   }
00732   _destroySimulatedObject = false ;
00733 }
00734 //------------------------------------------------------------------------------
00735 void ObjectDescriptor::addSon( ObjectDescriptor *newSon ) 
00736 {
00737    OMASSERT( newSon != 0 ) ;
00738    const ObjectDescriptor *duplicate = findDescendantNamed( newSon->getName() ) ;
00739    if( duplicate == 0 )
00740    {
00741      _sonsContainer.push_back( newSon ) ;
00742      newSon->_fathersDescription = this ;
00743    }
00744    else
00745    {
00746      OMTRACEID( OMK_DEBUG_OMK_OBJ,
00747                 "ObjectDescriptor::addSon named \"" << newSon->getName()
00748                 << "\" failed because descendant with the same name allready exists for object named \""
00749                 << getName() << "\"" ) ;
00750      // as respnsability is transfered and the son is not added, delete it
00751      delete newSon ;
00752    }
00753 }
00754 //------------------------------------------------------------------------------
00755 void ObjectDescriptor::removeSon( ObjectDescriptor *oldSon )
00756 {
00757   _sonsContainer.remove( oldSon ) ;
00758 }
00759 //------------------------------------------------------------------------------
00760 std::list< const ObjectDescriptor * > * ObjectDescriptor::getDescendants() const 
00761 {
00762   std::list< const ObjectDescriptor * > *result =
00763     new std::list< const ObjectDescriptor * >() ;
00764   return getDescendants( result ) ;
00765 }
00766 //------------------------------------------------------------------------------
00767 std::list< const ObjectDescriptor * > * ObjectDescriptor::getDescendants(
00768   std::list< const ObjectDescriptor * > * resultList ) const
00769 {
00770   for( SonsContainerType::const_iterator i = _sonsContainer.begin() ;
00771        i != _sonsContainer.end() ;
00772        ++i )
00773   {
00774     resultList->push_back( *i ) ;
00775     ( *i )->getDescendants( resultList ) ;
00776   }
00777   return resultList ;
00778 }
00779 //------------------------------------------------------------------------------
00780 std::list< ObjectDescriptor * > * ObjectDescriptor::getDescendants()
00781 {
00782   std::list< ObjectDescriptor * > *result = new std::list< ObjectDescriptor * >() ;
00783   return getDescendants( result ) ;
00784 }
00785 //------------------------------------------------------------------------------
00786 std::list< ObjectDescriptor * > * ObjectDescriptor::getDescendants(
00787   std::list< ObjectDescriptor * > *resultList )
00788 {
00789   for( SonsContainerType::const_iterator i = _sonsContainer.begin() ;
00790        i != _sonsContainer.end() ;
00791        ++i )
00792   {
00793     resultList->push_back( *i ) ;
00794     ( *i )->getDescendants( resultList ) ;
00795   }
00796   return resultList ;
00797 }
00798 //------------------------------------------------------------------------------
00799 const ObjectDescriptor *
00800 ObjectDescriptor::findDescendantNamed( const Name & name ) const 
00801 {
00802   const ObjectDescriptor *resul( 0 ) ;  
00803   if( name == getName() )
00804   {
00805     resul = this ;
00806   }
00807   else
00808   {
00809     SonsContainerType::const_iterator i = _sonsContainer.begin() ;
00810     while( ( resul == 0 ) && ( i != _sonsContainer.end() ) )
00811     {
00812       resul = ( *i )->findDescendantNamed( name ) ;
00813       ++i ;
00814     }
00815   }
00816   return resul ;
00817 }
00818 //------------------------------------------------------------------------------
00819 ObjectDescriptor *
00820 ObjectDescriptor::findDescendantNamed( const Name & name )
00821 {
00822   ObjectDescriptor *resul( 0 ) ;
00823   if( name == getName() )
00824   {
00825     resul = this ;
00826   }
00827   else
00828   {
00829     SonsContainerType::iterator i = _sonsContainer.begin() ;
00830     while( ( resul == 0 ) && ( i != _sonsContainer.end() ) )
00831     {
00832       resul = ( *i )->findDescendantNamed( name ) ;
00833       ++i ;
00834     }
00835   }
00836   return resul ;
00837 }
00838 //------------------------------------------------------------------------------
00839 void ObjectDescriptor::interpretConfigurationParameterAsListOfSons(
00840   SonsContainerType & listOfSons,
00841   MultipleConfigurationParameter * sonsDescription )
00842 {
00843   if( sonsDescription != 0 )
00844   {
00845     int nbSons = sonsDescription->getNumberOfSubItems() ;
00846     std::string sonName ;
00847     for( int i = 0 ; i < nbSons ; ++i )
00848     {
00849       ConfigurationParameterDescriptor * aGenericSonsDescription ;
00850       aGenericSonsDescription = sonsDescription->getSubDescriptorByPosition( i ) ;
00851       sonName = sonsDescription->getNameOfSubDescriptor( i ) ;
00852       MultipleConfigurationParameter * aSonsDescription ;
00853       aSonsDescription = dynamic_cast< MultipleConfigurationParameter * >(
00854         aGenericSonsDescription ) ;
00855       if( aSonsDescription != 0 )
00856       {
00857         ObjectDescriptor * descriptionOfSon =
00858           interpretConfigurationParameterAsObjectDescription(
00859             sonName, aSonsDescription ) ;
00860         listOfSons.push_back( descriptionOfSon );
00861       }
00862     }
00863   }
00864 }
00865 //------------------------------------------------------------------------------
00866 ObjectDescriptor * ObjectDescriptor::interpretConfigurationParameterAsObjectDescription(
00867   std::string objectName,
00868   MultipleConfigurationParameter *generalDescription ) 
00869 {
00870   OMASSERT( generalDescription != 0 ) ;
00871 
00872   ConfigurationParameterDescriptor *genericSubDescription =
00873     generalDescription->getSubDescriptorByName( "Class" ) ;
00874 
00875   if( genericSubDescription == 0 ) 
00876   {
00877     throw UserException( "Unable to extract a class for an ObjectDescriptor from a stream" ) ;
00878   }
00879 
00880   std::string classId = genericSubDescription->getAssociatedString() ;
00881 
00882   ConfigurationParameterDescriptor *configurationParameters =
00883     generalDescription->getSubDescriptorByName( "UserParams" ) ;
00884 
00885 
00886   ConfigurationParameterDescriptor *extensionsParameters =
00887     generalDescription->getSubDescriptorByName( "Extensions" ) ;
00888 
00889 
00890   MultipleConfigurationParameter *schedulingParameters =
00891     dynamic_cast< MultipleConfigurationParameter * >(
00892       generalDescription->getSubDescriptorByName( "Scheduling" ) ) ;
00893 
00894   ObjectDescriptor *result = new ObjectDescriptor( Name( objectName ),
00895                                                    Name( classId ),
00896                                                    schedulingParameters,
00897                                                    configurationParameters,
00898                                                    extensionsParameters ) ;
00899 
00900   genericSubDescription = generalDescription->getSubDescriptorByName( "Sons" ) ;
00901   generalDescription =
00902     dynamic_cast< MultipleConfigurationParameter * >( genericSubDescription ) ;
00903   if( generalDescription != 0 )
00904   {
00905     interpretConfigurationParameterAsListOfSons(
00906       result->_sonsContainer, generalDescription ) ;
00907     //for all the sons, connect to their father, only known here
00908     for( SonsContainerType::const_iterator i = result->_sonsContainer.begin() ;
00909          i != result->_sonsContainer.end() ;
00910          ++i )
00911     {
00912       ( *i )->_fathersDescription = result ;
00913     }
00914   }
00915   return result ;
00916 }

logo OpenMask

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

Generated with doxygen by Dimitri van Heesch ,   1997-2007