#include "munga.h" #pragma hdrstop #include "gauge.h" #include "gaugrend.h" extern void indent(int level); // in graph2d.cc //######################################################################### //############################# GaugeBase ################################# //######################################################################### GaugeBase::GaugeBase( ModeMask mode_mask, GaugeRenderer *new_renderer, unsigned int owner_ID, const char *identification_string ) : Node(Gauge::GaugeClassID), alreadyActivatedFlag(False) { Check_Pointer(this); modeMask = mode_mask; ownerID = owner_ID; renderer = new_renderer; identificationString = identification_string; stayInactive = True; // used by GaugeRenderer during activation //--------------------------------------------------- // If renderer exists, add to object list // (Not having a renderer allows for independent testing) //--------------------------------------------------- if (renderer != NULL) { Check(renderer); renderer->Add(this); } Check_Fpu(); } GaugeBase::~GaugeBase() { Check(this); Check_Fpu(); } Logical GaugeBase::TestInstance() const { return True; } void GaugeBase::BecameActive() { Check(this); //------------------------------------------------------ // Default method immediately inactivates the gaugeBase //------------------------------------------------------ DEBUG_STREAM << "BecameActive() has not been defined for '" << identificationString << "'. About to call Inactivate()\n"; Inactivate(); Check_Fpu(); } void GaugeBase::BecameInactive() { Check(this); Check_Fpu(); } void GaugeBase::Inactivate() { Check(this); if (renderer != NULL) { Check(renderer); renderer->Inactivate(this); } Check_Fpu(); } Logical GaugeBase::Update(GaugeRate /*rate_mask*/) { Check(this); //------------------------------------------------------ // Default method immediately inactivates the gaugeBase //------------------------------------------------------ DEBUG_STREAM << "Update() has not been defined for '" << identificationString << "'. About to call Inactivate()\n"; Inactivate(); Check_Fpu(); return False; } void GaugeBase::UpdateProfile(Scalar /*frame_percentage*/) { Check(this); Check_Fpu(); } void GaugeBase::ReportProfile() { Check(this); Check_Fpu(); } void GaugeBase::LinkToEntity(Entity */*entity*/) { Check(this); Check_Fpu(); } void GaugeBase::NotifyOfNewInterestingEntity(Entity */*entity*/) { Check(this); Check_Fpu(); } void GaugeBase::NotifyOfBecomingUninterestingEntity(Entity */*entity*/) { Check(this); Check_Fpu(); } int GaugeBase::DiscernTier() { Check(this); Check_Fpu(); return 0; } //######################################################################### //########################## GaugeBackground ############################## //######################################################################### GaugeBackground::GaugeBackground( ModeMask mode_mask, GaugeRenderer *new_renderer, unsigned int owner_ID, const char *identification_string ) : GaugeBase(mode_mask, new_renderer, owner_ID, identification_string) { Check_Pointer(this); Check_Fpu(); } //######################################################################### //######################## GraphicGaugeBackground ######################### //######################################################################### GraphicGaugeBackground::GraphicGaugeBackground( ModeMask mode_mask, GaugeRenderer *renderer, unsigned int owner_ID, int graphics_port_number, const char *identification_string ) : localView( renderer == NULL ? NULL : renderer->GetGraphicsPort(graphics_port_number) ), GaugeBackground(mode_mask, renderer, owner_ID, identification_string) { Check_Fpu(); } //######################################################################### //########################## GaugeConnection ############################## //######################################################################### GaugeConnection::GaugeConnection(int parameter_id) { Check_Pointer(this); parameterID = parameter_id; Check_Fpu(); } GaugeConnection::~GaugeConnection() { Check_Fpu(); } Logical GaugeConnection::TestInstance() const { Check_Pointer(this); return True; } void GaugeConnection::Update() { Fail("GaugeConnection::Update should not be called!\n"); } void GaugeConnection::ShowInstance(char *indent) { Check(this); std::cout << indent << "GaugeConnection:\n"; char temp[80]; Str_Copy(temp,indent, 80); Str_Cat(temp,"...", 80); std::cout << temp << "parameterID=" << parameterID << "\n" << std::flush; Check_Fpu(); } //######################################################################### //################################# Gauge ################################# //######################################################################### //---------------------------------------------------------------------------- // GaugeRate masks are used to spread out workload in a priority-based // manner. Each GaugeRate refers to the branch of a binary tree as shown: // // A = every frame // /--------------^--------------\ : // FIRST TIER: B C = 1/2 // /------^-------\ /------^-------\ : // 2ND: D E F G = 1/4 // /--^---\ /--^---\ /--^---\ /--^---\ : // H I J K L M N O = 1/8 // / \ / \ / \ / \ / \ / \ / \ / \ : // P Q R S T U V W X Y Z Z0 Z1 Z2 Z3 Z4 = 1/16 // // Each 'tier' down indicates an update rate half that of the one above it. // // Note that rates Z0..Z4 cannot be specified through the gauge renderer's // interpreter. They are available to automatically generated gauges, though. //---------------------------------------------------------------------------- GaugeRate Gauge::rateTable[31] = { gaugeRate_A, // every frame gaugeRate_B, // every other frame gaugeRate_C, gaugeRate_D, // every 4th frame gaugeRate_E, gaugeRate_F, gaugeRate_G, gaugeRate_H, // every 8th frame gaugeRate_I, gaugeRate_J, gaugeRate_K, gaugeRate_L, gaugeRate_M, gaugeRate_N, gaugeRate_O, gaugeRate_P, // every 16th frame gaugeRate_Q, gaugeRate_R, gaugeRate_S, gaugeRate_T, gaugeRate_U, gaugeRate_V, gaugeRate_W, gaugeRate_X, gaugeRate_Y, gaugeRate_Z, gaugeRate_Z0, gaugeRate_Z1, gaugeRate_Z2, gaugeRate_Z3, gaugeRate_Z4 }; //------------------------------------------------------------------- // Gauge::NextXXXTierGaugeRate() // - These functions attempt to spead out workload by returning the // next available 'GaugeRate' in a given 'tier'. // // The higher level tiers bump the lower level tier indices to // attempt to avoid placing too much load on the same higher-order // branch of the tree. //------------------------------------------------------------------- static int first_index = -1, second_index = -1, third_index = -1, fourth_index = -1; GaugeRate Gauge::NextFirstTierGaugeRate() { //---------------------------------------- // Generate first index //---------------------------------------- first_index = (++first_index) & 1; //---------------------------------------- // Bump other indices to avoid same branch //---------------------------------------- second_index += 2; third_index += 4; fourth_index += 8; //---------------------------------------- // Return rate mask //---------------------------------------- return rateTable[first_index + 1]; } GaugeRate Gauge::NextSecondTierGaugeRate() { //---------------------------------------- // Generate first index //---------------------------------------- second_index = (++second_index) & 3; //---------------------------------------- // Bump other indices to avoid same branch //---------------------------------------- third_index += 2; fourth_index += 4; //---------------------------------------- // Return rate mask //---------------------------------------- return rateTable[second_index + 3]; } GaugeRate Gauge::NextThirdTierGaugeRate() { //---------------------------------------- // Generate first index //---------------------------------------- third_index = (++third_index) & 7; //---------------------------------------- // Bump other indices to avoid same branch //---------------------------------------- fourth_index += 2; //---------------------------------------- // Return rate mask //---------------------------------------- return rateTable[third_index + 7]; } GaugeRate Gauge::NextFourthTierGaugeRate() { //---------------------------------------- // Generate first index //---------------------------------------- fourth_index = (++fourth_index) & 15; //---------------------------------------- // Return rate mask //---------------------------------------- return rateTable[fourth_index + 15]; } GaugeRate Gauge::ConvertIndexToRate(int index) { Verify(index >= 0); Verify(index < 32); return rateTable[index]; } Gauge::Gauge( GaugeRate new_rate, ModeMask mode_mask, GaugeRenderer *renderer, unsigned int owner_ID, const char *identification_string ): GaugeBase(mode_mask, renderer, owner_ID, identification_string), instanceList(this) { Check_Pointer(this); rate = new_rate; oldRate = new_rate; stayInactive = False; profileFramePercentage = (Scalar) 0; profileMaxFramePercentage = (Scalar) 0; profileCycles = 0; Check_Fpu(); } Gauge::~Gauge() { Check(this); RemoveAllConnections(); Check_Fpu(); } Logical Gauge::TestInstance() const { Check(&instanceList); # if 0 //-------------------------------------------------------------------- // Check all owned GaugeConnections //-------------------------------------------------------------------- ChainIteratorOf i(instanceList); GaugeConnection *the_connection; while ((the_connection=i.ReadAndNext()) != NULL) { Check(the_connection); } # endif //-------------------------------------------------------------------- // Check the base object //-------------------------------------------------------------------- return GaugeBase::TestInstance(); } void Gauge::ShowInstance(char *indent) { Check(this); ChainIteratorOf i(instanceList); GaugeConnection *the_connection; std::cout << indent << "Gauge:\n"; char temp[80]; Str_Copy(temp,indent, 80); Str_Cat(temp,"...", 80); std::cout << temp << "modeMask =" << modeMask << "\n"; std::cout << temp << "renderer =" << renderer << "\n"; std::cout << temp << "ownerID =" << ownerID << "\n"; std::cout << temp << "InstanceList -\n" << std::flush; Str_Cat(temp,"...", 80); while ((the_connection=i.ReadAndNext()) != NULL) { Check(the_connection); the_connection->ShowInstance(temp); } Check_Fpu(); } void Gauge::AddConnection(GaugeConnection *connection) { Check(this); Check(connection); instanceList.Add(connection); Check_Fpu(); } void Gauge::RemoveConnection(int parameter_ID) { Check(this); ChainIteratorOf i(instanceList); GaugeConnection *gauge_connection; while ((gauge_connection=i.ReadAndNext()) != NULL) { Check(gauge_connection); if (gauge_connection->parameterID == parameter_ID) { Unregister_Object(gauge_connection); delete gauge_connection; } } Check_Fpu(); } void Gauge::RemoveAllConnections() { Check(this); ChainIteratorOf i(instanceList); GaugeConnection *gauge_connection; while ((gauge_connection=i.ReadAndNext()) != NULL) { Check(gauge_connection); Unregister_Object(gauge_connection); delete gauge_connection; } Check_Fpu(); } void Gauge::Disable(Logical disable_state) { Check(this); if (disable_state) { rate = 0; BecameInactive(); } else { rate = oldRate; BecameActive(); } Check_Fpu(); } Logical Gauge::Update(GaugeRate rate_mask) { Check(this); Logical actually_ran = False; //----------------------------------------- // Update only if rate mask allows it //----------------------------------------- if (rate & rate_mask) { //----------------------------------------- // Update parameters //----------------------------------------- ChainIteratorOf i(instanceList); GaugeConnection *gauge_connection; while ((gauge_connection=i.ReadAndNext()) != NULL) { Check(gauge_connection); gauge_connection->Update(); } //----------------------------------------- // Execute gauge code //----------------------------------------- Execute(); actually_ran = True; } Check_Fpu(); return actually_ran; } void Gauge::Execute() { Fail("Gauge::Execute not overridden"); } struct TierLookup { GaugeRate rate; int tier; }; int Gauge::DiscernTier() { Check(this); TierLookup *tier_pointer; static TierLookup tier_lookup[] = { {gaugeRate_A, 0 }, {gaugeRate_B, 1 }, {gaugeRate_C, 1 }, {gaugeRate_D, 2 }, {gaugeRate_E, 2 }, {gaugeRate_F, 2 }, {gaugeRate_G, 2 }, {gaugeRate_H, 3 }, {gaugeRate_I, 3 }, {gaugeRate_J, 3 }, {gaugeRate_K, 3 }, {gaugeRate_L, 3 }, {gaugeRate_M, 3 }, {gaugeRate_N, 3 }, {gaugeRate_O, 3 }, {gaugeRate_P, 4 }, {gaugeRate_Q, 4 }, {gaugeRate_R, 4 }, {gaugeRate_S, 4 }, {gaugeRate_T, 4 }, {gaugeRate_U, 4 }, {gaugeRate_V, 4 }, {gaugeRate_W, 4 }, {gaugeRate_X, 4 }, {gaugeRate_Y, 4 }, {gaugeRate_Z, 4 }, {gaugeRate_Z0,4 }, {gaugeRate_Z1,4 }, {gaugeRate_Z2,4 }, {gaugeRate_Z3,4 }, {gaugeRate_Z4,4 }, {0,0} }; for (tier_pointer=tier_lookup; tier_pointer->rate != 0; ++tier_pointer) { if (tier_pointer->rate == rate) { Check_Fpu(); return tier_pointer->tier; } } Check_Fpu(); return 0; } void Gauge::UpdateProfile(Scalar frame_percentage) { Check(this); //--------------------------------------------- // Keep worst case //--------------------------------------------- if (profileMaxFramePercentage < frame_percentage) { profileMaxFramePercentage = frame_percentage; } //--------------------------------------------- // Keep running total //--------------------------------------------- profileFramePercentage += frame_percentage; //--------------------------------------------- // Prevent overflow //--------------------------------------------- if (++profileCycles > 16384) { profileFramePercentage /= (Scalar) 2; profileCycles >>= 1; } Check_Fpu(); } void Gauge::ReportProfile() { Check(this); int i; DEBUG_STREAM << identificationString << std::flush; for(i=strlen(identificationString); i<32; ++i) { DEBUG_STREAM << "." << std::flush; } if (profileCycles > 0) { Scalar average = profileFramePercentage / (Scalar)profileCycles; char buffer[80]; sprintf(buffer, "%6d %6.4f %6.4f\n", profileCycles, average, profileMaxFramePercentage ); DEBUG_STREAM << buffer << std::flush; } else { DEBUG_STREAM << "never ran.\n" << std::flush; } //---------------------------------------- // Reset maximum percentage //---------------------------------------- profileMaxFramePercentage = (Scalar) 0; Check_Fpu(); } //######################################################################### //############################# GraphicGauge ############################# //######################################################################### GraphicGauge::GraphicGauge( GaugeRate new_rate, ModeMask mode_mask, GaugeRenderer *renderer, unsigned int owner_ID, int graphics_port_number, const char *identification_string ) : Gauge(new_rate, mode_mask, renderer, owner_ID, identification_string), localView( renderer == NULL ? NULL : renderer->GetGraphicsPort(graphics_port_number) ) { Check_Fpu(); } GraphicGauge::~GraphicGauge() { Check(this); Check_Fpu(); } Logical GraphicGauge::TestInstance() const { Check(&localView); Check_Fpu(); return Gauge::TestInstance(); } void GraphicGauge::ShowInstance(char *indent) { Check(this); std::cout << indent << "GraphicGauge:\n"; char temp[80]; Str_Copy(temp,indent, 80); Str_Cat(temp,"...", 80); localView.ShowInstance(temp); Gauge::ShowInstance(temp); Check_Fpu(); } #if defined(TEST_CLASS) # include "gauge.tcp" #endif