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