00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLPeriodicSlot.h"
00028
00029
00030 using namespace OSDL::Events ;
00031 using namespace OSDL::Engine ;
00032
00033 using namespace Ceylan::Log ;
00034
00035 using std::string ;
00036 using std::list ;
00037
00038
00039
00040
00041 PeriodicSlot::PeriodicSlot( Period periodicity ) :
00042 _period( periodicity ),
00043 _currentSubSlot( 0 )
00044 {
00045
00046
00047
00048
00049
00050
00051 _subslots = new ListOfPeriodicalActiveObjects * [ _period ] ;
00052
00053 _subslotWeights = new Weight[ _period ] ;
00054
00055
00056
00057 for ( Period i = 0; i < _period; i++ )
00058 {
00059 _subslots[i] = 0 ;
00060 _subslotWeights[ i ] = 0 ;
00061 }
00062
00063 }
00064
00065
00066
00067 PeriodicSlot::~PeriodicSlot() throw()
00068 {
00069
00070
00071
00072 for ( Period i = 0; i < _period; i++ )
00073 {
00074
00075 if ( _subslots[i] != 0 )
00076 {
00077
00078 Ceylan::Uint32 remainingCount = 0 ;
00079
00080
00081 for ( ListOfPeriodicalActiveObjects::const_iterator it =
00082 _subslots[i]->begin() ; it != _subslots[i]->end(); it++ )
00083 {
00084
00085 if ( (*it) != 0 )
00086 remainingCount++ ;
00087
00088 }
00089
00090 if ( remainingCount != 0 )
00091 LogPlug::warning( "PeriodicSlot destructor: "
00092 "for slot in charge of period "
00093 + Ceylan::toString( _period ) + ", subslot #"
00094 + Ceylan::toString( i ) + " was still containing "
00095 + Ceylan::toString( remainingCount )
00096 + " periodical object(s)." ) ;
00097
00098 delete _subslots[i] ;
00099
00100 }
00101
00102 }
00103
00104 delete [] _subslots ;
00105
00106 delete [] _subslotWeights ;
00107
00108 }
00109
00110
00111
00112 Period PeriodicSlot::add( PeriodicalActiveObject & newObject )
00113 {
00114
00115 Period chosenSubSlot ;
00116
00117
00118
00119
00120
00121
00122
00123
00124 switch( newObject.getPolicy() )
00125 {
00126
00127 case strict:
00128 chosenSubSlot = ( _currentSubSlot + 1 ) % _period ;
00129 break ;
00130
00131 case relaxed:
00132 chosenSubSlot = getLeastBusySubSlot() ;
00133 break ;
00134
00135 default:
00136 throw SchedulingException( "PeriodicSlot::add: "
00137 "unexpected scheduling policy." ) ;
00138
00139 }
00140
00141
00142 addInSubSlot( newObject, chosenSubSlot ) ;
00143
00144 return chosenSubSlot ;
00145
00146 }
00147
00148
00149
00150 void PeriodicSlot::removeFromSubslot( PeriodicalActiveObject & object )
00151 {
00152
00153 Period subslot = object.getSubslotNumber() ;
00154
00155 LogPlug::trace( "PeriodicSlot::removeFromSubslot: for object '"
00156 + object.toString() + "', using subslot #"
00157 + Ceylan::toString(subslot) ) ;
00158
00159
00160
00161
00162
00163
00164
00165
00166 if ( _subslots[ subslot ] == 0 )
00167 throw SchedulingException( "PeriodicSlot::removeFromSubslot failed: "
00168 "sub-slot #" + Ceylan::toString( subslot ) + " does not exist." ) ;
00169
00170 for ( list<PeriodicalActiveObject *>::iterator it =
00171 _subslots[ subslot ]->begin(); it != _subslots[ subslot ]->end(); it++ )
00172 {
00173
00174 if ( (*it) == & object )
00175 {
00176
00177
00178 _subslotWeights[ subslot ] -= object.getWeight() ;
00179 *it = 0 ;
00180
00181 LogPlug::trace( "PeriodicSlot::removeFromSubslot: "
00182 "removed from sub-slot #" + Ceylan::toString( subslot )
00183 + ", new slot state is: " + toString() ) ;
00184
00185
00186
00187 return ;
00188
00189 }
00190 }
00191
00192 throw SchedulingException( "PeriodicSlot::removeFromSubslot failed: "
00193 "periodical object " + object.toString() + " not found." ) ;
00194
00195 }
00196
00197
00198
00199 bool PeriodicSlot::onNextTick( SimulationTick newTick )
00200 {
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 Period deducedSubSlot = getSubSlotForSimulationTick( newTick ) ;
00211
00212
00213
00214
00215
00216
00217
00218
00219 if ( _currentSubSlot != deducedSubSlot || _period == 1 )
00220 {
00221
00222
00223 _currentSubSlot = ( _currentSubSlot + 1 ) % _period ;
00224
00225 if ( _currentSubSlot != deducedSubSlot )
00226 LogPlug::warning(
00227 "PeriodicSlot::onNextTick: expected next sub-slot to be "
00228 + Ceylan::toString( _currentSubSlot ) + ", got "
00229 + Ceylan::toString( deducedSubSlot )
00230 + " for simulation tick "
00231 + Ceylan::toString( newTick ) + "." ) ;
00232
00233
00234
00235
00236
00237
00238 _currentSubSlot = deducedSubSlot ;
00239
00240 if ( ! activateAllObjectsInSubSlot( _currentSubSlot, newTick ) )
00241 {
00242
00243 LogPlug::trace( "PeriodicSlot::onNextTick: removing sub-slot "
00244 + Ceylan::toString( _currentSubSlot ) ) ;
00245
00246
00247 delete _subslots[ _currentSubSlot ] ;
00248 _subslots[ _currentSubSlot ] = 0 ;
00249
00250 if ( isEmpty() )
00251 return false ;
00252
00253 }
00254
00255 return true ;
00256
00257 }
00258 else
00259 {
00260
00261
00262
00263
00264
00265
00266 if ( newTick != 0 )
00267 {
00268
00269
00270 LogPlug::warning( "PeriodicSlot::onNextTick: "
00271 "apparently called multiple times for simulation time "
00272 + Ceylan::toString( newTick )
00273 + " (last activated sub-slot was "
00274 + Ceylan::toString( _currentSubSlot )
00275 + "), no more activation performed." ) ;
00276 }
00277
00278 return true ;
00279
00280 }
00281 }
00282
00283
00284
00285 void PeriodicSlot::onSimulationSkipped( SimulationTick skipped )
00286 {
00287
00288 Period subSlot = getSubSlotForSimulationTick( skipped ) ;
00289
00290
00291
00292 if ( _subslots[subSlot] != 0 )
00293 {
00294 for ( ListOfPeriodicalActiveObjects::iterator it =
00295 _subslots[subSlot]->begin() ;
00296 it != _subslots[subSlot]->end(); it++ )
00297 {
00298
00299
00300 if ( *it != 0 )
00301 (*it)->onSkip( skipped ) ;
00302
00303 }
00304 }
00305
00306
00307 _currentSubSlot = subSlot ;
00308
00309 }
00310
00311
00312
00313 Period PeriodicSlot::getPeriod() const
00314 {
00315
00316 return _period ;
00317
00318 }
00319
00320
00321
00322 bool PeriodicSlot::isEmpty() const
00323 {
00324
00325 for ( Period i = 0; i < _period; i++ )
00326 {
00327
00328 if ( _subslots[i] != 0 )
00329 if ( ! _subslots[i]->empty() )
00330 return false ;
00331
00332 }
00333
00334 return true ;
00335
00336 }
00337
00338
00339
00340 const string PeriodicSlot::toString( Ceylan::VerbosityLevels level ) const
00341 {
00342
00343 string res = "Periodic slot whose period is "
00344 + Ceylan::toString( _period )
00345 + ". Current sub-slot is "
00346 + Ceylan::toString( _currentSubSlot ) ;
00347
00348 LogPlug::trace( res ) ;
00349
00350 if ( level == Ceylan::low )
00351 return res ;
00352
00353 if ( level == Ceylan::medium )
00354 {
00355
00356 Ceylan::Uint32 objectCount = 0 ;
00357 Weight weightCount = 0 ;
00358
00359
00360 for ( Period i = 0; i < _period; i++ )
00361 {
00362 if ( _subslots[i] != 0 )
00363 objectCount +=
00364 static_cast<Ceylan::Uint32>( _subslots[i]->size() ) ;
00365
00366 weightCount += _subslotWeights[i] ;
00367 }
00368
00369 return res + ". " + Ceylan::toString( objectCount )
00370 + " active objects are registered in its slots, "
00371 "for a total weight of "
00372 + Ceylan::toString( weightCount ) + "." ;
00373 }
00374
00375 list<string> l ;
00376
00377 for ( Period i = 0; i < _period; i++ )
00378 {
00379 if ( ( _subslots[i] != 0 ) && ( ! _subslots[i]->empty() ) )
00380 l.push_back( "sub-slot #" + Ceylan::toString( i ) + " contains "
00381 + Ceylan::toString(
00382 static_cast<Ceylan::Uint32>( _subslots[i]->size() ) )
00383 + " active object(s), for a total weight of "
00384 + Ceylan::toString( _subslotWeights[i] ) + "." ) ;
00385 else
00386 l.push_back( "subslot #" + Ceylan::toString( i ) + " is empty." ) ;
00387 }
00388
00389 return res + Ceylan::formatStringList( l ) ;
00390
00391 }
00392
00393
00394
00395 Period PeriodicSlot::getSubSlotForSimulationTick( SimulationTick tick ) const
00396 {
00397
00398 return ( tick % _period ) ;
00399
00400 }
00401
00402
00403
00404 void PeriodicSlot::addInSubSlot( PeriodicalActiveObject & newObject,
00405 Period targetSubslot )
00406 {
00407
00408 if ( _subslots[ targetSubslot ] == 0 )
00409 _subslots[ targetSubslot ] = new ListOfPeriodicalActiveObjects() ;
00410
00411 _subslots[ targetSubslot ]->push_back( & newObject ) ;
00412 _subslotWeights[ targetSubslot ] += newObject.getWeight() ;
00413
00414 }
00415
00416
00417
00418 Period PeriodicSlot::getLeastBusySubSlot() const
00419 {
00420
00421 Weight minWeight = _subslotWeights[ 0 ] ;
00422 Period minIndex = 0 ;
00423
00424
00425 for ( Period i = 1; i < _period; i++ )
00426 {
00427 if ( _subslotWeights[ i ] < minWeight )
00428 {
00429 minIndex = i ;
00430 minWeight = _subslotWeights[ i ] ;
00431 }
00432 }
00433
00434 return minIndex ;
00435
00436 }
00437
00438
00439
00440 bool PeriodicSlot::activateAllObjectsInSubSlot( Period subSlot,
00441 SimulationTick currentTime )
00442 {
00443
00444 if ( _subslots[ subSlot ] == 0 )
00445 {
00446
00447
00448 return true ;
00449
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 ListOfPeriodicalActiveObjects * subslotList = _subslots[ subSlot ] ;
00465
00466
00467 ListOfPeriodicalActiveObjects::iterator it = subslotList->begin() ;
00468
00469
00470
00471
00472
00473
00474
00475 while( it != subslotList->end() )
00476 {
00477
00478
00479
00480
00481
00482 if ( *it == 0 )
00483 {
00484
00485 LogPlug::trace( "PeriodicSlot::activateAllObjectsInSubSlot: "
00486 "removing a previously emptied entry." ) ;
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 it = subslotList->erase( it ) ;
00497
00498 }
00499 else
00500 {
00501
00502 (*it)->onActivation( currentTime ) ;
00503 it++ ;
00504
00505 }
00506
00507 }
00508
00509
00510 if ( subslotList->empty() )
00511 return false ;
00512
00513
00514 return true ;
00515
00516 }
00517