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
00028 #include "nPriorizing.h"
00029 #include "nNetwork.h"
00030 #include "tMemManager.h"
00031
00032 tDEFINE_REFOBJ( nBandwidthTask )
00033 tDEFINE_REFOBJ( nBandwidthArbitrator )
00034
00035
00036
00037
00038
00039
00040 void nBandwidthTask::SetType ( nType t )
00041 {
00042 tASSERT( priorizer_ );
00043
00044 this->RemoveFromHeap();
00045 type_ = t;
00046 priorizer_->Tasks( type_ ).Insert( this );
00047 }
00048
00049
00050 void nBandwidthTask::DoPriorize()
00051 {
00052 SetVal( priority_ * waiting_, *this->Heap() );
00053 }
00054
00055
00056 tHeapBase *nBandwidthTask::Heap() const
00057 {
00058 tASSERT( priorizer_ );
00059
00060 return &priorizer_->Tasks( type_ );
00061 }
00062
00063 nBandwidthTask::~nBandwidthTask()
00064 {
00065 this->RemoveFromHeap();
00066 }
00067
00068 nBandwidthTask::nBandwidthTask( nType type )
00069 : type_( type )
00070 , priorizer_( NULL )
00071 {
00072 waiting_ = .01f;
00073 priority_ = 0.1f;
00074 }
00075
00076
00077
00078
00079
00080
00081 void nBandwidthTaskPriorizer::Insert( nBandwidthTask* task )
00082 {
00083 nTaskHeap& heap = this->Tasks( task->Type() );
00084
00085 heap.Insert( task );
00086
00087 tReferencer< nBandwidthTask >::AddReference( task );
00088
00089 task->priorizer_ = this;
00090
00091 task->Priorize();
00092
00093 this->OnChange();
00094 }
00095
00096
00097 nBandwidthTask* nBandwidthTaskPriorizer::PeekNext( nType type )
00098 {
00099 nTaskHeap& heap = this->Tasks( type );
00100
00101 if ( heap.Len() <= 0 )
00102 {
00103 return NULL;
00104 }
00105
00106 return heap(0);
00107 }
00108
00109
00110 tJUST_CONTROLLED_PTR<nBandwidthTask> nBandwidthTaskPriorizer::Next( nType type )
00111 {
00112 nTaskHeap& heap = this->Tasks( type );
00113
00114 if ( heap.Len() <= 0 )
00115 {
00116 return NULL;
00117 }
00118
00119 tJUST_CONTROLLED_PTR<nBandwidthTask> ret = heap.Remove(0);
00120
00121 tReferencer< nBandwidthTask >::ReleaseReference( ret );
00122
00123 ret->priorizer_ = NULL;
00124
00125 this->OnChange();
00126
00127 return ret;
00128 }
00129
00130
00131
00132
00133
00134 nBandwidthArbitrator::nBandwidthArbitrator()
00135 {
00136 sceduler_ = NULL;
00137 }
00138
00139 nBandwidthArbitrator::~nBandwidthArbitrator()
00140 {
00141 if ( sceduler_ )
00142 {
00143 sceduler_->RemoveArbitrator( *this );
00144 }
00145
00146 tASSERT( NULL == sceduler_ );
00147
00148 this->RemoveFromHeap();
00149 }
00150
00151
00152 bool nBandwidthArbitrator::Fill( nSendBuffer& buffer, nBandwidthControl& control )
00153 {
00154
00155 bool ret = false;
00156
00157
00158 nType type = this->FirstType();
00159 if ( type < nBandwidthTask::Type_Count )
00160 {
00161 REAL totalPriority = 0.0f;
00162
00163 bool first = true;
00164 bool goon = true;
00165 while ( goon )
00166 {
00167 goon = false;
00168
00169 tJUST_CONTROLLED_PTR< nBandwidthTask > next = this->PeekNext( type );
00170 if ( next )
00171 {
00172 REAL priority = next->Priority();
00173 REAL value = next->Val();
00174
00175
00176 if ( !first || value * this->TimeScale() > -control.Score() )
00177 {
00178
00179 if ( priority * this->PacketOverhead() > totalPriority * next->EstimateSize() )
00180 {
00181
00182 next = this->Next( type );
00183
00184
00185 next->Execute( buffer, control );
00186
00187
00188 totalPriority += priority;
00189
00190
00191 goon = true;
00192 ret = true;
00193 }
00194 }
00195 }
00196
00197 first = false;
00198 }
00199 }
00200
00201
00202 this->SetVal( this->Val() - 100.0f, *this->Heap() );
00203
00204 return ret;
00205 }
00206
00207
00208 void nBandwidthArbitrator::Timestep( REAL dt )
00209 {
00210 for ( int i = 0; i < nBandwidthTask::Type_Count; ++i )
00211 {
00212 nType type = nType(i);
00213
00214 nTaskHeap& heap = this->Tasks( type );
00215 int j;
00216
00217 static tArray< nBandwidthTask* > tasks;
00218 tasks.SetLen( 0 );
00219
00220
00221 for ( j = heap.Len()-1; j>=0; --j )
00222 {
00223 tasks[j] = heap(j);
00224 }
00225
00226 for ( j = tasks.Len()-1; j>=0; --j )
00227 {
00228 tasks(j)->Timestep( dt );
00229 }
00230 }
00231
00232 this->OnChange();
00233 }
00234
00235
00236 nBandwidthArbitrator::nType nBandwidthArbitrator::FirstType() const
00237 {
00238 for ( int i = 0; i < nBandwidthTask::Type_Count; ++i )
00239 {
00240 nType type = nType(i);
00241 if ( this->Tasks(type).Len() > 0 )
00242 {
00243 return type;
00244 }
00245 }
00246
00247 return nBandwidthTask::Type_Count;
00248 }
00249
00250
00251 void nBandwidthArbitrator::OnChange()
00252 {
00253 REAL value = 0.0f;
00254
00255 for ( int i = 0; i < nBandwidthTask::Type_Count; ++i )
00256 {
00257 nType type = nType(i);
00258 const nTaskHeap& heap = this->Tasks(type);
00259 if ( heap.Len() > 0 )
00260 {
00261 value += heap(0)->Val();
00262 }
00263 }
00264
00265 this->SetVal( value, *this->Heap() );
00266 }
00267
00268 tHeapBase* nBandwidthArbitrator::Heap() const
00269 {
00270 if ( !sceduler_ )
00271 {
00272 return NULL;
00273 }
00274
00275 return &sceduler_->arbitratorHeap_;
00276 }
00277
00278
00279
00280
00281 nBandwidthSceduler::~nBandwidthSceduler()
00282 {
00283 while ( this->arbitratorList_.Len() > 0 )
00284 {
00285 this->RemoveArbitrator( *this->arbitratorList_(0) );
00286 }
00287 }
00288
00289 void nBandwidthSceduler::UseBandwidth( REAL dt )
00290 {
00291 int i;
00292
00293
00294 for ( i = this->arbitratorList_.Len()-1; i>=0; --i )
00295 {
00296 this->arbitratorList_(i)->Timestep( dt );
00297 }
00298
00299
00300 if ( this->arbitratorHeap_.Len() <= 0 )
00301 {
00302 return;
00303 }
00304
00305 bool goon = true;
00306 while( goon )
00307 {
00308 goon = false;
00309
00310 nBandwidthArbitrator* arbitrator = this->arbitratorHeap_(0);
00311 tASSERT( arbitrator );
00312
00313 goon = arbitrator->UseBandwidth( dt );
00314 }
00315 }
00316
00317
00318 void nBandwidthSceduler::AddArbitrator ( nBandwidthArbitrator& arbitrator )
00319 {
00320 tASSERT( NULL == arbitrator.sceduler_ );
00321
00322 tJUST_CONTROLLED_PTR< nBandwidthArbitrator > keepalive( &arbitrator );
00323
00324 this->arbitratorHeap_.Insert( &arbitrator );
00325 this->arbitratorList_.Add( &arbitrator );
00326
00327 arbitrator.sceduler_ = this;
00328 }
00329
00330
00331 void nBandwidthSceduler::RemoveArbitrator ( nBandwidthArbitrator& arbitrator )
00332 {
00333 tASSERT( this == arbitrator.sceduler_ );
00334
00335 tJUST_CONTROLLED_PTR< nBandwidthArbitrator > keepalive( &arbitrator );
00336
00337 this->arbitratorHeap_.Remove( &arbitrator );
00338 this->arbitratorList_.Remove( &arbitrator );
00339
00340 arbitrator.sceduler_ = NULL;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 class nBandwitdhDistributor: public nBandwidthArbitrator
00350 {
00351 public:
00352 nSendBuffer& SendBuffer() { return buffer_; }
00353 const nSendBuffer& SendBuffer() const { return buffer_; }
00354 nBandwidthControl& BandwidthControl() { return control_; }
00355 const nBandwidthControl& BandwidthControl() const { return control_; }
00356 protected:
00357 private:
00358 virtual bool DoUseBandwidth( REAL dt );
00359
00360 virtual REAL TimeScale(){ return 0.1f; }
00361 virtual REAL PacketOverhead(){ return 60.0f; }
00362
00363 nSendBuffer buffer_;
00364 nBandwidthControl control_;
00365 };
00366
00367
00368
00369
00370
00371
00372
00373 bool nBandwitdhDistributor::DoUseBandwidth( REAL dt )
00374 {
00375 return this->Fill( this->buffer_, this->control_ );
00376 }
00377
00378
00379
00380
00381 class nBandwidthTaskMessage: public nBandwidthTask
00382 {
00383 public:
00384 nBandwidthTaskMessage( nType type, nMessage& message );
00385
00386 nMessage& Message() const { return *message_; }
00387 protected:
00388 virtual void DoExecute( nSendBuffer& buffer, nBandwidthControl& control );
00389 virtual int DoEstimateSize() const;
00390
00391 private:
00392 tJUST_CONTROLLED_PTR< nMessage > message_;
00393 };
00394
00395
00396
00397
00398
00399
00400
00401
00402 nBandwidthTaskMessage::nBandwidthTaskMessage( nType type, nMessage& message )
00403 :nBandwidthTask( type ), message_( &message )
00404 {
00405 }
00406
00407
00408 void nBandwidthTaskMessage::DoExecute( nSendBuffer& buffer, nBandwidthControl& control )
00409 {
00410 buffer.AddMessage( *message_, &control );
00411 }
00412
00413
00414 int nBandwidthTaskMessage::DoEstimateSize() const
00415 {
00416 return message_->DataLen();
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 #ifdef DEBUG
00437
00438 static nDescriptor testDescriptor( 399, NULL, NULL, "test" );
00439
00440
00441 #include "nNetObject.h"
00442
00443 class nTestObject: public nNetObject
00444 {
00445 public:
00446 nTestObject( nMessage& m ): nNetObject( m ){}
00447 nTestObject(){};
00448 virtual nDescriptor& CreatorDescriptor() const;
00449 virtual bool AcceptClientSync() const{return true;}
00450 };
00451
00452 nDescriptor& nTestObject::CreatorDescriptor() const
00453 {
00454 static nNOInitialisator< nTestObject > cd( 398, "nTestObject" );
00455 return cd;
00456 }
00457
00458
00459 class PriorizingTester
00460 {
00461 public:
00462 PriorizingTester()
00463 {
00464 nBandwidthSceduler sceduler;
00465
00466 {
00467 tJUST_CONTROLLED_PTR< nBandwidthArbitrator > distributor = tNEW( nBandwitdhDistributor );
00468 sceduler.AddArbitrator( *distributor );
00469
00470 {
00471 nMessage* mess = tNEW( nMessage( testDescriptor) );
00472 tJUST_CONTROLLED_PTR< nBandwidthTask > messageTask = tNEW( nBandwidthTaskMessage ) ( nBandwidthTask::Type_Vital, *mess );
00473 distributor->Insert( messageTask );
00474 sceduler.UseBandwidth( 1.0f );
00475 distributor->Insert( messageTask );
00476 sceduler.UseBandwidth( 1.0f );
00477 distributor->Insert( messageTask );
00478 }
00479
00480 {
00481 tJUST_CONTROLLED_PTR< nNetObject > object = tNEW( nTestObject );
00482 tJUST_CONTROLLED_PTR< nBandwidthTask > objectTask = tNEW( nBandwidthTaskCreate ) ( nBandwidthTask::Type_Vital, *object );
00483 objectTask->AddPriority( 1.0f );
00484 distributor->Insert( objectTask );
00485 }
00486 }
00487
00488 sceduler.UseBandwidth( 1.0f );
00489 sceduler.UseBandwidth( 1.0f );
00490 sceduler.UseBandwidth( 1.0f );
00491 }
00492 };
00493
00494
00495
00496 #endif
00497