diff options
Diffstat (limited to 'trunk/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp')
-rw-r--r-- | trunk/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp | 795 |
1 files changed, 795 insertions, 0 deletions
diff --git a/trunk/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp b/trunk/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp new file mode 100644 index 00000000000..f8fd77a1709 --- /dev/null +++ b/trunk/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp @@ -0,0 +1,795 @@ +// $Id$ + +#include "ace/OS.h" +#include "ace/Singleton.h" +#include "ace/Null_Mutex.h" + +#include "orbsvcs/Runtime_Scheduler.h" +#include "orbsvcs/Sched/Reconfig_Scheduler.h" +#include "orbsvcs/Sched/Reconfig_Sched_Utils.h" +#include "orbsvcs/Scheduler_Factory.h" + +#if ! defined (__ACE_INLINE__) +#include "orbsvcs/Scheduler_Factory.inl" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(orbsvcs, + Scheduler_Factory, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +// Initialize static class members. +RtecScheduler::Scheduler_ptr ACE_Scheduler_Factory::server_ = 0; +ACE_Scheduler_Factory::Factory_Status ACE_Scheduler_Factory::status_ = + ACE_Scheduler_Factory::UNINITIALIZED; + + +RtecScheduler::Period_t ACE_Scheduler_Factory::period_default_ = 0; +RtecScheduler::Threads_t ACE_Scheduler_Factory::threads_default_ = 0; +RtecScheduler::Importance_t ACE_Scheduler_Factory::importance_default_ = RtecScheduler::MEDIUM_IMPORTANCE; +RtecScheduler::Criticality_t ACE_Scheduler_Factory::criticality_default_ = RtecScheduler::HIGH_CRITICALITY; +RtecScheduler::RT_Info_Enabled_Type_t ACE_Scheduler_Factory::rt_info_enable_state_default_ = RtecScheduler::RT_INFO_NON_VOLATILE; + +RtecScheduler::Period_t ACE_Scheduler_Factory::period_default() +{ + return period_default_; +} + +RtecScheduler::Threads_t ACE_Scheduler_Factory::threads_default() +{ + return threads_default_; +} + +RtecScheduler::Importance_t ACE_Scheduler_Factory::importance_default() +{ + return importance_default_; +} + +RtecScheduler::Criticality_t ACE_Scheduler_Factory::criticality_default() +{ + return criticality_default_; +} + +void ACE_Scheduler_Factory::period_default(RtecScheduler::Period_t period_default) +{ + period_default_ = period_default; +} + +void ACE_Scheduler_Factory::threads_default(RtecScheduler::Threads_t threads_default) +{ + threads_default_ = threads_default; +} + +void ACE_Scheduler_Factory::importance_default(RtecScheduler::Importance_t importance_default) +{ + importance_default_ = importance_default; +} + +void ACE_Scheduler_Factory::criticality_default(RtecScheduler::Criticality_t criticality_default) +{ + criticality_default_ = criticality_default; +} + +RtecScheduler::RT_Info_Enabled_Type_t ACE_Scheduler_Factory::rt_info_enable_state_default() +{ + return rt_info_enable_state_default_; +} + +void ACE_Scheduler_Factory::rt_info_enable_state_default(RtecScheduler::RT_Info_Enabled_Type_t rt_info_enable_state_default) +{ + rt_info_enable_state_default_ = rt_info_enable_state_default; +} + +// This symbols are extern because the automatic template +// instantiation mechanism in SunCC gets confused otherwise. +int TAO_SF_config_count = -1; +ACE_Scheduler_Factory::POD_Config_Info* TAO_SF_config_info = 0; +int TAO_SF_entry_count = -1; +ACE_Scheduler_Factory::POD_RT_Info* TAO_SF_rt_info = 0; +int TAO_SF_dependency_count = -1; +ACE_Scheduler_Factory::POD_Dependency_Info* TAO_SF_dep_info = 0; + +struct ACE_Scheduler_Factory_Data +{ + // = TITLE + // Helper struct, to encapsulate the singleton static server and + // ACE_TSS objects. We can't use ACE_Singleton directly, because + // construction of ACE_Runtime_Scheduler takes arguments. + +/* WSOA merge - commented out + ACE_Runtime_Scheduler scheduler_; + // The static runtime scheduler. +*/ + + TAO_Reconfig_Scheduler<TAO_MUF_FAIR_Reconfig_Sched_Strategy, ACE_SYNCH_MUTEX> scheduler_; + // The scheduler. + + ACE_TSS<ACE_TSS_Type_Adapter<RtecScheduler::Preemption_Priority_t> > + preemption_priority_; + // The dispatch queue number of the calling thread. For access by + // applications; must be set by either the application or Event + // Channel. + + ACE_Scheduler_Factory_Data (void) + : scheduler_ (TAO_SF_config_count, + TAO_SF_config_info, + TAO_SF_entry_count, + TAO_SF_rt_info, + TAO_SF_dependency_count, + TAO_SF_dep_info, + 0), + preemption_priority_ () + { + } +}; + +static ACE_Scheduler_Factory_Data *ace_scheduler_factory_data = 0; + +int ACE_Scheduler_Factory::use_runtime (int cc, + POD_Config_Info cfgi[], + int ec, + POD_RT_Info rti[]) +{ + if (server_ != 0 || TAO_SF_entry_count != -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT("ACE_Scheduler_Factory::use_runtime - ") + ACE_TEXT("server already configured\n")), + -1); + TAO_SF_config_count = cc; + TAO_SF_config_info = cfgi; + TAO_SF_entry_count = ec; + TAO_SF_rt_info = rti; + status_ = ACE_Scheduler_Factory::RUNTIME; + + return 0; +} + +static RtecScheduler::Scheduler_ptr +static_server (void) +{ + RtecScheduler::Scheduler_ptr server_ = 0; + + // This isn't thread safe, but the static instance that it replaces + // wasn't thread safe either. Hola, Sr. Sandiego :-) If it needs to + // be made thread safe, it should be protected using double-checked + // locking. + if (! ace_scheduler_factory_data && + (ace_scheduler_factory_data = + ACE_Singleton<ACE_Scheduler_Factory_Data, + ACE_Null_Mutex>::instance ()) == 0) + return 0; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + server_ = ace_scheduler_factory_data->scheduler_._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("ACE_Scheduler_Factory - configured static server\n"))); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + ACE_TEXT("ACE_Scheduler_Factory::config_runtime - ") + ACE_TEXT("cannot allocate server\n")); + } + ACE_ENDTRY; + + return server_; +} + +int +ACE_Scheduler_Factory::use_config (CosNaming::NamingContext_ptr naming) +{ + return ACE_Scheduler_Factory::use_config (naming, + "ScheduleService"); +} + +int +ACE_Scheduler_Factory::use_config (CosNaming::NamingContext_ptr naming, + const char* name) +{ + if (server_ != 0 || TAO_SF_entry_count != -1) + // No errors, runtime execution simply takes precedence over + // config runs. + return 0; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + CosNaming::Name schedule_name (1); + schedule_name.length (1); + schedule_name[0].id = CORBA::string_dup (name); + CORBA::Object_var objref = + naming->resolve (schedule_name + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + server_ = + RtecScheduler::Scheduler::_narrow(objref.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + server_ = 0; + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + ACE_TEXT("ACE_Scheduler_Factory::use_config - ") + ACE_TEXT(" exception while resolving server\n")); + } + ACE_ENDTRY; + + status_ = ACE_Scheduler_Factory::CONFIG; + return 0; +} + +int +ACE_Scheduler_Factory::server (RtecScheduler::Scheduler_ptr sptr) +{ + if (server_ != 0 || TAO_SF_entry_count != -1) + return -1; + + server_ = RtecScheduler::Scheduler::_duplicate (sptr); + return 0; +} + +RtecScheduler::Scheduler_ptr +ACE_Scheduler_Factory::server (void) +{ + if (server_ == 0 && TAO_SF_entry_count != -1) + server_ = static_server (); + + if (server_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT("ACE_Scheduler_Factor::server - ") + ACE_TEXT("no scheduling service configured\n")), + 0); + return server_; +} + +static char header[] = +"// $Id $\n\n" +"// This file was automatically generated by the Scheduler_Factory.\n" +"// Before editing the file please consider generating it again.\n" +"\n" +"#include \"orbsvcs/Scheduler_Factory.h\"\n" +"\n"; + +static char footer[] = +"\n" +"// This sets up Scheduler_Factory to use the runtime version.\n" +"int scheduler_factory_setup = \n" +" ACE_Scheduler_Factory::use_runtime (configs_size, configs, infos_size, infos);\n" +"\n" +"// EOF\n"; + +static char start_anomalies_found[] = +"\n// The following scheduling anomalies were detected:\n"; + +static char start_anomalies_none[] = +"\n// There were no scheduling anomalies.\n"; + +static char start_infos[] = +"\n\nstatic ACE_Scheduler_Factory::POD_RT_Info infos[] = {\n"; + +static char end_infos[] = +"};\n\n" +"static int infos_size = sizeof(infos)/sizeof(infos[0]);\n\n"; + +static char end_infos_empty[] = +"};\n\n" +"static int infos_size = 0;\n\n"; + +static char start_dependencies[] = +"\n\nstatic ACE_Scheduler_Factory::POD_Dependency_Info dependencies[] = {\n"; + +static char end_dependencies[] = +"};\n\n" +"static int dependencies_size = sizeof(dependencies)/sizeof(dependencies[0]);\n\n"; + +static char end_dependencies_empty[] = +"};\n\n" +"static int dependencies_size = 0;\n\n"; + +static char start_configs[] = +"\nstatic ACE_Scheduler_Factory::POD_Config_Info configs[] = {\n"; + +static char end_configs[] = +"};\n\n" +"static int configs_size = sizeof(configs)/sizeof(configs[0]);\n\n"; + +static char end_configs_empty[] = +"};\n\n" +"static int configs_size = 0;\n\n"; + +int ACE_Scheduler_Factory::dump_schedule + (const RtecScheduler::RT_Info_Set& infos, + const RtecScheduler::Dependency_Set& dependencies, + const RtecScheduler::Config_Info_Set& configs, + const RtecScheduler::Scheduling_Anomaly_Set& anomalies, + const char* file_name, + const char* rt_info_format, + const char* dependency_format, + const char* config_info_format, + int dump_disabled_infos, + int dump_disabled_dependencies) +{ + u_int i; + char entry_point [BUFSIZ]; + + // Default format for printing RT_Info output. + if (rt_info_format == 0) + rt_info_format = "{%20s, /* entry_point */\n" + "%10d, /* handle */\n" + "%10d, /* worst_case_execution_time */,\n" + "%10d, /* typical_execution_time */,\n" + "%10d, /* cached_execution_time */,\n" + "%10d, /* period */\n" + "(RtecScheduler::Criticality_t) %d, /* [ VL_C = 0, L_C = 1, M_C = 2, H_C = 3, VH_C = 4] */\n" + "(RtecScheduler::Importance_t) %d, /* [ VL_I = 0, L_I = 1, M_I = 2, H_I = 3, VH_I = 4] */\n" + "%10d, /* quantum */\n" + "%10d, /* threads */\n" + "%10d, /* priority */\n" + "%10d, /* preemption_subpriority */\n" + "%10d, /* preemption_priority */\n" + "(RtecScheduler::Info_Type_t) %d, /* [OPERATION = 0, CONJUNCTION = 1, DISJUNCTION = 2, REMOTE_DEPENDANT = 3] */\n" + "(RtecScheduler::RT_Info_Enabled_Type_t) %d } /* [RT_INFO_DISABLED = 0, RT_INFO_ENABLED = 1, RT_INFO_NON_VOLATILE = 2] */\n"; + + + // Default format for printing dependency output. + if (dependency_format == 0) + dependency_format = " { (RtecScheduler::Dependency_Type_t) %d, %10d, " + "%10d, %10d," + "(RtecScheduler::Dependency_Enabled_Type_t) %d }"; + + // Default format for printing Config_Info output. + if (config_info_format == 0) + config_info_format = " { %10d, %10d, " + "(RtecScheduler::Dispatching_Type_t) %d }"; + + FILE* file = stdout; + if (file_name != 0) + { + file = ACE_OS::fopen (ACE_TEXT_CHAR_TO_TCHAR(file_name), ACE_TEXT("w")); + if (file == 0) + return -1; + } + ACE_OS::fprintf (file, header); + + // Indicate anomalies encountered during scheduling. + + ACE_OS::fprintf(file, (anomalies.length () > 0 + ? start_anomalies_found + : start_anomalies_none)); + + for (i = 0; i < anomalies.length (); ++i) + { + const RtecScheduler::Scheduling_Anomaly& anomaly = anomalies[i]; + switch (anomaly.severity) + { + case RtecScheduler::ANOMALY_FATAL: + ACE_OS::fprintf(file, "FATAL: "); + break; + + case RtecScheduler::ANOMALY_ERROR: + ACE_OS::fprintf(file, "ERROR: "); + break; + + case RtecScheduler::ANOMALY_WARNING: + ACE_OS::fprintf(file, "// WARNING: "); + break; + + default: + ACE_OS::fprintf(file, "// UNKNOWN: "); + break; + } + + ACE_OS::fprintf (file, + "%s\n", + (const char *) anomaly.description); + } + + // Print out banner indicating which infos are dumped. + if (dump_disabled_infos) + { + ACE_OS::fprintf (file, "\n// Both enabled and disabled RT_Infos were dumped to this file.\n\n"); + } + else + { + ACE_OS::fprintf (file, "\n// Only enabled RT_Infos were dumped to this file.\n\n"); + } + + // Print out operation QoS info. + ACE_OS::fprintf (file, start_infos); + + for (i = 0; + i < infos.length (); + ++i) + { + const RtecScheduler::RT_Info& info = infos[i]; + + if (dump_disabled_infos + || info.enabled == RtecScheduler::RT_INFO_ENABLED + || info.enabled == RtecScheduler::RT_INFO_NON_VOLATILE) + { + if (i != 0) + // Finish previous line. + ACE_OS::fprintf(file, ",\n"); + + const RtecScheduler::RT_Info& info = infos[i]; + + // Put quotes around the entry point name, exactly as it is stored. + ACE_OS::sprintf (entry_point, + "\"%s\"", + (const char *) info.entry_point); + + // @@ TODO Eventually the TimeT structure will be a 64-bit + // unsigned int, we will have to change this dump method then. + ACE_OS::fprintf (file, + rt_info_format, + entry_point, + info.handle, + ACE_CU64_TO_CU32 (info.worst_case_execution_time), + ACE_CU64_TO_CU32 (info.typical_execution_time), + ACE_CU64_TO_CU32 (info.cached_execution_time), + info.period, + info.criticality, + info.importance, + ACE_CU64_TO_CU32 (info.quantum), + info.threads, + info.priority, + info.preemption_subpriority, + info.preemption_priority, + info.info_type, + info.enabled); + } + } + + // Finish last line. + ACE_OS::fprintf(file, "\n"); + + if (infos.length () > 0) + ACE_OS::fprintf (file, end_infos); + else + ACE_OS::fprintf (file, end_infos_empty); + + // Print out banner indicating which dependencies are dumped. + if (dump_disabled_dependencies) + { + ACE_OS::fprintf (file, "\n// Both enabled and disabled dependencies were dumped to this file.\n\n"); + } + else + { + ACE_OS::fprintf (file, "\n// Only enabled dependencies were dumped to this file.\n\n"); + } + + // Print out operation dependency info. + ACE_OS::fprintf (file, start_dependencies); + + for (i = 0; + i < dependencies.length (); + ++i) + { + const RtecScheduler::Dependency_Info& dep = dependencies[i]; + + if (dump_disabled_infos + || dep.enabled == RtecBase::DEPENDENCY_ENABLED + || dep.enabled == RtecBase::DEPENDENCY_NON_VOLATILE) + { + // Finish previous line. + if (i != 0) + { + ACE_OS::fprintf (file, ",\n"); + } + + ACE_OS::fprintf (file, + dependency_format, + dep.dependency_type, + dep.number_of_calls, + dep.rt_info, + dep.rt_info_depended_on, + dep.enabled); + } + } + + // Finish last line. + ACE_OS::fprintf (file, "\n"); + + if (dependencies.length () > 0) + ACE_OS::fprintf (file, end_dependencies); + else + ACE_OS::fprintf (file, end_dependencies_empty); + + + // Print out queue configuration info. + ACE_OS::fprintf (file, start_configs); + + for (i = 0; + i < configs.length (); + ++i) + { + if (i != 0) + // Finish previous line. + ACE_OS::fprintf (file, ",\n"); + + const RtecScheduler::Config_Info& config = configs[i]; + ACE_OS::fprintf (file, + config_info_format, + config.preemption_priority, + config.thread_priority, + config.dispatching_type); + } + + // Finish last line. + ACE_OS::fprintf (file, "\n"); + + if (configs.length () > 0) + ACE_OS::fprintf (file, end_configs); + else + ACE_OS::fprintf (file, end_configs_empty); + + ACE_OS::fprintf (file, footer); + ACE_OS::fclose (file); + return 0; +} + +void ACE_Scheduler_Factory::log_scheduling_entry(TAO_Reconfig_Scheduler_Entry * entry, FILE* file) +{ + + if( entry == 0 ) + { + ACE_OS::fprintf (file, "Entry is NULL"); + return; + } + + // Print out the actual rt_info data + const char* rt_info_format = "{%20s, /* entry_point */\n" + "%10d, /* handle */\n" + "%10d, /* period */\n" + "%10d, /* criticality */\n" + "%10d, /* threads */\n" + "%10d, /* priority */\n" + "%10d, /* preemption_subpriority */\n" + "%10d, /* preemption_priority */\n" + "%10d /* enabled */\n"; + + TAO_RT_Info_Ex* actual_info = entry->actual_rt_info(); + + ACE_OS::fprintf (file, + rt_info_format, + actual_info->entry_point.in(), + actual_info->handle, + actual_info->period, + actual_info->criticality, + actual_info->threads, + actual_info->priority, + actual_info->preemption_subpriority, + actual_info->preemption_priority, + actual_info->enabled); + + + // Print out the current admitted tuple + const char* admitted_tuple_format = " {" + "%13d, /* handle */\n" + "%13d, /* rate_index */\n" + "%13d, /* period */\n" + "%13d, /* criticality */\n" + "%13d, /* priority */\n" + "%13d, /* preemption_subpriority */\n" + "%13d, /* preemption_priority */\n" + "%13d } /* enabled */\n"; + + TAO_RT_Info_Tuple* current_admitted_tuple = entry->current_admitted_tuple(); + + ACE_OS::fprintf(file, "\n Current admitted Tuple:\n"); + if( current_admitted_tuple == 0 ) + { + ACE_OS::fprintf (file, " =>NONE_ADMITTED\n"); + } + else + { + ACE_OS::fprintf (file, + admitted_tuple_format, + current_admitted_tuple->handle, + current_admitted_tuple->rate_index, + current_admitted_tuple->period, + current_admitted_tuple->criticality, + current_admitted_tuple->priority, + current_admitted_tuple->preemption_subpriority, + current_admitted_tuple->preemption_priority, + current_admitted_tuple->enabled); + } + + // Print out the orig_tuple_subset_ + ACE_OS::fprintf(file, "\n Original Tuple Subset\n {\n"); + log_tuple_subset(entry->orig_tuple_subset(), file); + ACE_OS::fprintf(file, "\n }"); + + // Print out the prop_tuple_subset_ + ACE_OS::fprintf(file, "\n Propagated Tuple Subset\n {\n"); + log_tuple_subset(entry->prop_tuple_subset(), file); + ACE_OS::fprintf(file, "\n }\n}"); + + +} + +void ACE_Scheduler_Factory::log_tuple_subset(TUPLE_SET & tuple_subset, + FILE* file) +{ + TAO_RT_Info_Tuple **tuple_ptr_ptr; + const char* subset_tuple_format = " {\n" + "%13d, /* handle */\n" + "%13d, /* rate_index */\n" + "%13d, /* period */\n" + "%13d, /* criticality */\n" + "%13d, /* threads */\n" + "%13d, /* priority */\n" + "%13d, /* preemption_subpriority */\n" + "%13d, /* preemption_priority */\n" + "%13d } /* enabled */\n"; + + TUPLE_SET_ITERATOR + tuple_iter (tuple_subset); + + + while (tuple_iter.done () == 0) + { + // Get a pointer to the tuple COPY under the iterator. + if (tuple_iter.next (tuple_ptr_ptr) == 0 + || tuple_ptr_ptr == 0 || ((*tuple_ptr_ptr) == 0) ) + { + ACE_OS::fprintf (file, "{ NULL TUPLE POINTER }\n"); + } + else + { + + ACE_OS::fprintf (file, + subset_tuple_format, + (*tuple_ptr_ptr)->handle, + (*tuple_ptr_ptr)->rate_index, + (*tuple_ptr_ptr)->period, + (*tuple_ptr_ptr)->criticality, + (*tuple_ptr_ptr)->threads, + (*tuple_ptr_ptr)->priority, + (*tuple_ptr_ptr)->preemption_subpriority, + (*tuple_ptr_ptr)->preemption_priority, + (*tuple_ptr_ptr)->enabled); + } + + tuple_iter.advance (); + } +} + +int +ACE_Scheduler_Factory::log_scheduling_entries(TAO_Reconfig_Scheduler_Entry ** entry_ptr_array, + long entry_ptr_array_size, + const char* file_name) +{ + // Open the file + FILE* file = stdout; + if (file_name != 0) + { + file = ACE_OS::fopen (file_name, ACE_TEXT ("w")); + if (file == 0) + return -1; + } + + + // Iterate through the array. The index is the (handle - 1) of the rt_info in the array + for(int index = 0; index < entry_ptr_array_size; ++index) + { + ACE_OS::fprintf(file, "\n\nScheduler Entry Array contents\n"); + TAO_Reconfig_Scheduler_Entry * entry = entry_ptr_array[index]; + + log_scheduling_entry(entry, file); + + + } + + + ACE_OS::fclose (file); + return 0; + +} + +void +ACE_Scheduler_Factory::log_scheduling_tuples( + TAO_RT_Info_Tuple ** tuple_ptr_array, + long tuple_ptr_array_size, + const char* file_name) +{ + // Open the file + FILE* file = stdout; + if (file_name != 0) + { + file = ACE_OS::fopen (file_name, ACE_TEXT ("w")); + if (file == 0) + return; + } + + static const char subset_tuple_format[] = + " {\n" + "%13d, /* handle */\n" + "%13lu, /* rate_index */\n" + "%13d, /* period */\n" + "%13d, /* criticality */\n" + "%13d, /* priority */\n" + "%13d, /* preemption_subpriority */\n" + "%13d, /* preemption_priority */\n" + "%13d } /* enabled */\n"; + + for (int ndx = 0; ndx < tuple_ptr_array_size; ndx++) + { + fprintf(file, + subset_tuple_format, + tuple_ptr_array[ndx]->handle, + tuple_ptr_array[ndx]->rate_index, + tuple_ptr_array[ndx]->period, + tuple_ptr_array[ndx]->criticality, + tuple_ptr_array[ndx]->priority, + tuple_ptr_array[ndx]->preemption_subpriority, + tuple_ptr_array[ndx]->preemption_priority, + tuple_ptr_array[ndx]->enabled); + } + + ACE_OS::fclose (file); +} +#if defined (HPUX) && !defined (__GNUG__) + // aCC can't handle RtecScheduler::Preemption_Priority_t used as an operator + // name. + typedef CORBA::Long RtecScheduler_Preemption_Priority_t; +#endif /* HPUX && !g++ */ + +RtecScheduler::Preemption_Priority_t +ACE_Scheduler_Factory::preemption_priority (void) +{ + // Return whatever we've got. The application or Event Channel is + // responsible for making sure that it was set. + if (ace_scheduler_factory_data->preemption_priority_.ts_object ()) + { + ACE_TSS_Type_Adapter<RtecScheduler::Preemption_Priority_t> *tss = + ace_scheduler_factory_data->preemption_priority_; + // egcs 1.0.1 raises an internal compiler error if we implicitly + // call the type conversion operator. So, call it explicitly. +#if defined (HPUX) && !defined (__GNUG__) + const RtecScheduler::Preemption_Priority_t preemption_priority = + static_cast<RtecScheduler::Preemption_Priority_t> (tss->operator RtecScheduler_Preemption_Priority_t ()); +#else + const RtecScheduler::Preemption_Priority_t preemption_priority = + static_cast<RtecScheduler::Preemption_Priority_t> (tss->operator RtecScheduler::Preemption_Priority_t ()); +#endif /* HPUX && !g++ */ + return preemption_priority; + } + else + return static_cast<RtecScheduler::Preemption_Priority_t> (-1); +} + +void +ACE_Scheduler_Factory::set_preemption_priority + (const RtecScheduler::Preemption_Priority_t preemption_priority) +{ + // Probably don't need this, because it should be safe to assume + // that static_server () was called before this function. But just + // in case . . . + if (!ace_scheduler_factory_data + && (ace_scheduler_factory_data = + ACE_Singleton<ACE_Scheduler_Factory_Data, + ACE_Null_Mutex>::instance ()) == 0) + return; + + ace_scheduler_factory_data->preemption_priority_-> +#if defined (HPUX) && !defined (__GNUG__) + // aCC can't handle the typedef. + operator RtecScheduler_Preemption_Priority_t & () = preemption_priority; +#else + operator RtecScheduler::Preemption_Priority_t & () = preemption_priority; +#endif /* HPUX && !g++ */ +} + +#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION) +template ACE_Singleton<ACE_Scheduler_Factory_Data, ACE_Null_Mutex> *ACE_Singleton<ACE_Scheduler_Factory_Data, ACE_Null_Mutex>::singleton_; +#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */ + +TAO_END_VERSIONED_NAMESPACE_DECL |