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 }
Documentation generated on Mon Jun 9 11:45:57 2008 |
Generated with doxygen by Dimitri van Heesch , 1997-2007 |