/* ************************************************************************* ArmageTron -- Just another Tron Lightcycle Game in 3D. Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) ************************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *************************************************************************** */ #ifndef ArmageTron_nPRIORIZING_H #define ArmageTron_nPRIORIZING_H #include "defs.h" #include "tHeap.h" class nBandwidthSceduler; class nBandwidthArbitrator; class nSendBuffer; class nBandwidthControl; class nBandwidthTask; class nBandwidthTaskPriorizer; tDECLARE_REFOBJ( nBandwidthTask ); tDECLARE_REFOBJ( nBandwidthArbitrator ); // small task that will eat away some bandwidth class nBandwidthTask: public tHeapElement, public tReferencable< nBandwidthTask > { friend class tReferencable< nBandwidthTask >; friend class nBandwidthTaskPriorizer; public: enum nType { Type_System = 0, // extremely important task for the integrety of the connection Type_Vital = 1, // task important for someone's survival in the game Type_Casual = 2, // not so important task Type_Count = 3 }; void Execute( nSendBuffer& buffer, nBandwidthControl& control ) { this->DoExecute( buffer, control ); } // executes the small task void Priorize() { if ( this->priorizer_ ) this->DoPriorize(); } // rethinks priority int EstimateSize ( void ) const { return this->DoEstimateSize(); } // estimate bandwidth usage nType Type ( void ) const { return type_; } // returns the type of task REAL Priority ( void ) const { return priority_; } // returns the priority ( event gets important after 1/priority_ seconds ) void SetType ( nType t ); // sets the task type void AddPriority ( REAL add ) { priority_ += add; this->Priorize(); } // adds priority void Timestep ( REAL dt ) { waiting_ += dt; this->Priorize(); } // adds time protected: virtual void DoExecute( nSendBuffer& buffer, nBandwidthControl& control ) = 0; // executes whatever it has to do virtual int DoEstimateSize() const = 0; // estimate bandwidth usage virtual void DoPriorize(); // rethinks priority virtual tHeapBase *Heap() const; // in wich heap are we? virtual ~nBandwidthTask(); nBandwidthTask( nType type ); private: nType type_; // type of this task REAL priority_; // something terrible happens if this task is not executed within 1/priority_ seconds REAL waiting_; // time this task is already waiting ( plus small offset ) nBandwidthTaskPriorizer* priorizer_; // the arbitrator taking care of this task }; // bandwidth priorizer: selects bandwidth taks class nBandwidthTaskPriorizer { public: typedef tHeap< nBandwidthTask > nTaskHeap; typedef nBandwidthTask::nType nType; nTaskHeap& Tasks( nType t ) { tASSERT( 0 <= t && t < nBandwidthTask::Type_Count ); return tasks_[ t ]; } const nTaskHeap& Tasks( nType t ) const { tASSERT( 0 <= t && t < nBandwidthTask::Type_Count ); return tasks_[ t ]; } void Insert( nBandwidthTask* task ); // inserts a task into the queue nBandwidthTask* PeekNext( nType type ); // returns the top priority task virtual ~nBandwidthTaskPriorizer(){} protected: tJUST_CONTROLLED_PTR Next( nType type ); // removes and returns the top priority task private: virtual void OnChange(){}; // called on every change of data nTaskHeap tasks_[ nBandwidthTask::Type_Count ]; }; // bandwidth arbitrator: executes bandwidth tasks class nBandwidthArbitrator: public nBandwidthTaskPriorizer, public tHeapElement, public tListMember, public tReferencable< nBandwidthArbitrator > { friend class nBandwidthSceduler; friend class tReferencable< nBandwidthArbitrator >; public: bool Fill( nSendBuffer& buffer, nBandwidthControl& control ); // fills the send buffer with top priority messages void Timestep( REAL dt ); // advances timers of all tasks bool UseBandwidth( REAL dt ){ return DoUseBandwidth( dt ); } // consumes some bandwidth protected: nBandwidthArbitrator(); ~nBandwidthArbitrator(); private: nType FirstType() const; // determines the type of the message to send next virtual void OnChange(); // called on every change of data virtual bool DoUseBandwidth( REAL dt ) = 0; virtual tHeapBase* Heap() const; virtual REAL TimeScale(){ return 0.1f; } // higher values let really urgent messages be sent even if the bandwidth control objectd virtual REAL PacketOverhead(){ return 60.0f; } // overhead in bytes per sent packet. Determines average package size nBandwidthSceduler* sceduler_; }; // sceduler: distributes bandwidth around all arbitrators class nBandwidthSceduler { friend class nBandwidthArbitrator; public: ~nBandwidthSceduler(); void UseBandwidth( REAL dt ); // consumes bandwidth void AddArbitrator ( nBandwidthArbitrator& arbitrator ); // adds an arbitrator void RemoveArbitrator ( nBandwidthArbitrator& arbitrator ); // removes an arbitrator private: tList< nBandwidthArbitrator, false, true > arbitratorList_; // arbitrators managed by the sceduler tHeap< nBandwidthArbitrator > arbitratorHeap_; // arbitrators managed by the sceduler organized in priority heap }; class nNetObject; // object syncing or creating bandwidth task class nBandwidthTaskObject: public nBandwidthTask { public: nBandwidthTaskObject( nType type, nNetObject& object ); virtual ~nBandwidthTaskObject(); nNetObject& Object() const { return *object_; } protected: virtual int DoEstimateSize() const; // estimate bandwidth usage private: tJUST_CONTROLLED_PTR< nNetObject > object_; }; // object syncing bandwidth task class nBandwidthTaskSync: public nBandwidthTaskObject { public: nBandwidthTaskSync( nType type, nNetObject& object ) : nBandwidthTaskObject( type, object ) {} protected: virtual void DoExecute( nSendBuffer& buffer, nBandwidthControl& control ); // executes whatever it has to do }; // object syncing bandwidth task class nBandwidthTaskCreate: public nBandwidthTaskObject { public: nBandwidthTaskCreate( nType type, nNetObject& object ) : nBandwidthTaskObject( type, object ) {} protected: virtual void DoExecute( nSendBuffer& buffer, nBandwidthControl& control ); // executes whatever it has to do }; #endif