// -*- C++ -*- //============================================================================= /** * @file Strategy_Scheduler.h * * @author Chris Gill */ //============================================================================= #ifndef STRATEGY_SCHEDULER_H #define STRATEGY_SCHEDULER_H #include /**/ "ace/pre.h" #include "orbsvcs/Sched/DynSched.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL // forward declaration of the abstract base class for scheduler strategies class ACE_Scheduler_Strategy; ///////////////////////////////// // Strategized scheduler class // ///////////////////////////////// /** * @class ACE_Strategy_Scheduler * * @brief ACE_Strategy_Scheduler * * Strategized scheduler implementation. Provides an implementation * of all strategy specific scheduling mechanisms, which relies on the * methods of the associated strategy class. */ class TAO_RTSched_Export ACE_Strategy_Scheduler : public ACE_DynScheduler { // public interface public: /// = Constructor. ACE_Strategy_Scheduler (ACE_Scheduler_Strategy &strategy); /// = Virtual destructor. virtual ~ACE_Strategy_Scheduler (); /// = Assigns priorities to the sorted dispatch schedule, /// according to the strategy's priority comparison operator. status_t assign_priorities ( Dispatch_Entry **dispatches, u_int count, ACE_Unbounded_Set &anomaly_set); /// = Assigns dynamic and static sub-priorities to the sorted dispatch /// schedule, according to the strategy's subpriority comparisons. status_t assign_subpriorities ( Dispatch_Entry **dispatches, u_int count, ACE_Unbounded_Set &anomaly_set); /// = Determine the minimum critical priority number. virtual Preemption_Priority minimum_critical_priority (); private: /// = Schedules a dispatch entry into the timeline being created. virtual status_t schedule_timeline_entry (Dispatch_Entry &dispatch_entry, ACE_Unbounded_Queue &reschedule_queue); /// = Sets up the schedule in the order generated by the strategy. virtual status_t sort_dispatches (Dispatch_Entry **dispatches, u_int count); /// = Strategy for comparing and sorting dispatch entries. ACE_Scheduler_Strategy &strategy_; ACE_Strategy_Scheduler (const ACE_Strategy_Scheduler &); ACE_Strategy_Scheduler &operator= (const ACE_Strategy_Scheduler &); }; //////////////////////////////////////// // Factory for strategized schedulers // //////////////////////////////////////// /** * @class ACE_Strategy_Scheduler_Factory * * @brief ACE_Strategy_Scheduler_Factory * * Provides a type parameterized factory method that constructs * and returns a scheduler that uses the given scheduling strategy */ template class ACE_Strategy_Scheduler_Factory { public: /// = Constructs and returns a scheduler strategized with /// an instance of the the parameterized strategy type. static ACE_Strategy_Scheduler * create (RtecScheduler::Preemption_Priority_t minimum_critical_priority); }; ////////////////////////// // Scheduler Strategies // ////////////////////////// /** * @class ACE_Scheduler_Strategy * * @brief ACE_Scheduler_Strategy * * Abstract Base Class for scheduling strategies: each derived class * must define an ordering strategy for dispatch entries based on a * specific scheduling algorithm. */ class TAO_RTSched_Export ACE_Scheduler_Strategy { public: /// = Constructor. ACE_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// Destructor. virtual ~ACE_Scheduler_Strategy (void); /** * = Compares two dispatch entries in strategy specific high to low * priority ordering: returns -1 if the first Dispatch_Entry is greater * in the order, 0 if they are equivalent, or 1 if the second * Dispatch_Entry is greater in the order. */ virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry) = 0; /// = Sorts the dispatch entry link pointer array according to /// the specific sort order defined by the strategy. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count) = 0; /// = Determines the minimum critical priority number. virtual ACE_DynScheduler::Preemption_Priority minimum_critical_priority (); /** * = Compares two dispatch entries in strategy specific high to low * dynamic subpriority ordering: returns -1 if the first Dispatch_Entry * is greater in the order, 0 if they are equivalent, or 1 if the * second Dispatch_Entry is greater in the order. */ virtual int dynamic_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry) = 0; /// = Returns a dynamic subpriority value /// for the given timeline entry at the current time. virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time) = 0; /** * = Provides a lowest level ordering based first on importance * (descending), and then on the dependency topological sort finishing * time (ascending). */ virtual int static_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Provide the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry) = 0; protected: /** * = Compares two dispatch entries using the specific priority, dynamic * subpriority, and static subpriority method definitions provided by * the derived strategy class to produce the strategy specific sort * ordering: returns -1 if the first Dispatch_Entry is greater in the * order, 0 if they are equivalent, or 1 if the second Dispatch_Entry is * greater in the order. This is an example of the Template Method * pattern (and also of Pree's Unification Metapattern), in which * derived classes provide definitions of the methods on which the * sort_comp Template Method relies. */ int sort_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = The minimum critical priority number for the strategy. ACE_DynScheduler::Preemption_Priority minimum_critical_priority_; }; /** * @class ACE_MUF_Scheduler_Strategy * * @brief ACE_MUF_Scheduler_Strategy * * Defines "schedule" method using Maximum Urgency First * scheduling algorithm. */ class TAO_RTSched_Export ACE_MUF_Scheduler_Strategy : public ACE_Scheduler_Strategy { public: /// = Constructor. ACE_MUF_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// = Virtual destructor. virtual ~ACE_MUF_Scheduler_Strategy (); /// = Returns an instance of the strategy. static ACE_MUF_Scheduler_Strategy *instance (); /** * = Compares two dispatch entries by maximum criticality: returns -1 if * the first Dispatch_Entry is greater in the order, 0 if they're * equivalent, or 1 if the second Dispatch_Entry is greater in the order. */ virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Sorts the dispatch entry link pointer array /// in descending urgency order. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count); /// = Determines the minimum critical priority number. virtual ACE_DynScheduler::Preemption_Priority minimum_critical_priority (); /// = Provides the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry); protected: /** * = Returns a dynamic subpriority value at the current time for * the given timeline entry: if the operation has * non-negative laxity, then the value is positive, and a lower * laxity gives a higher dynamic subpriority; if the operation * has negative laxity, the value is the (negative) laxity value. */ virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time); /** * = Orders two dispatch entries by ascending laxity: returns -1 if the * first Dispatch_Entry is greater in the order, 0 if they're equivalent, * 1 if the second Dispatch_Entry is greater in the order. */ virtual int dynamic_subpriority_comp ( const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); private: // = Comparison function to pass to qsort: calls instance ()->sort_comp (). #if defined (ACE_HAS_WINCE) static int _cdecl sort_function (void *arg1, void *arg2); #else static int sort_function (void *arg1, void *arg2); #endif // ACE_HAS_WINCE /// Instance of the strategy. static ACE_MUF_Scheduler_Strategy *instance_; }; /** * @class ACE_RMS_Scheduler_Strategy * * @brief ACE_RMS_Scheduler_Strategy * * Defines "schedule" method using Rate Monotonic * Scheduling algorithm. */ class TAO_RTSched_Export ACE_RMS_Scheduler_Strategy : public ACE_Scheduler_Strategy { public: /// = Constructor. ACE_RMS_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// = Virtual destructor. virtual ~ACE_RMS_Scheduler_Strategy (); /// Returns an instance of the strategy. static ACE_RMS_Scheduler_Strategy *instance (); /** * = Compares two dispatch entries by minimum period: returns -1 if the * first Dispatch_Entry is greater in the order, 0 if they're equivalent, * or 1 if the second Dispatch_Entry is greater in the order. */ virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Sorts the dispatch entry link pointer array in /// descending RMS (rate) order. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count); /// = Determine the minimum critical priority number. virtual ACE_DynScheduler::Preemption_Priority minimum_critical_priority (); /// = Provide the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry); protected: /// = Just returns 0: all operations have /// the same dynamic subpriority value. virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time); /// = All dispatches in a given priority level have the same dynamic /// subpriority under RMS: just returns 0. virtual int dynamic_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); private: /// = Comparison function to pass to qsort: calls instance ()->sort_comp (). static int sort_function (void *arg1, void *arg2); /// = Instance of the strategy. static ACE_RMS_Scheduler_Strategy *instance_; }; /** * @class ACE_MLF_Scheduler_Strategy * * @brief ACE_MLF_Scheduler_Strategy * * Defines "schedule" method using Minimum Laxity First * scheduling algorithm. */ class TAO_RTSched_Export ACE_MLF_Scheduler_Strategy : public ACE_Scheduler_Strategy { public: /// = Constructor. ACE_MLF_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// = Virtual destructor. virtual ~ACE_MLF_Scheduler_Strategy (); /// = Returns an instance of the strategy. static ACE_MLF_Scheduler_Strategy *instance (); /// = Just returns 0, as all dispatch entries are of equivalent /// static priority under MLF. virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Sorts the dispatch entry link pointer array in ascending laxity order. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count); /// = Provide the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry); protected: /** * = Returns a dynamic subpriority value at the current time for * the given timeline entry: if the operation has * non-negative laxity, then the value is positive, and a lower * laxity gives a higher dynamic subpriority; if the operation * has negative laxity, the value is the (negative) laxity value. */ virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time); /** * = Orders two dispatch entries by ascending laxity: returns -1 if the * first Dispatch_Entry is greater in the order, 0 if they're equivalent, * or 1 if the second Dispatch_Entry is greater in the order. */ virtual int dynamic_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); private: /// = Comparison function to pass to qsort: calls instance ()->sort_comp (). static int sort_function (void *arg1, void *arg2); /// = Instance of the strategy static ACE_MLF_Scheduler_Strategy *instance_; }; /** * @class ACE_EDF_Scheduler_Strategy * * @brief ACE_EDF_Scheduler_Strategy * * Defines "schedule" method using Earliest Deadline First * scheduling algorithm. */ class TAO_RTSched_Export ACE_EDF_Scheduler_Strategy : public ACE_Scheduler_Strategy { public: /// = Default constructor. ACE_EDF_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// = Virtual destructor. virtual ~ACE_EDF_Scheduler_Strategy (); /// = Returns an instance of the strategy. static ACE_EDF_Scheduler_Strategy *instance (); /// = Returns 0, as all dispatch entries are of equivalent /// priority under EDF. virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Sorts the dispatch entry link pointer array /// in ascending deadline (period) order. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count); /// = Provide the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry); protected: /** * = Returns a dynamic subpriority value at the current time for the * given timeline entry: if the operation has non-negative * time to deadline, then value is positive, and a shorter time to * deadline gives a higher dynamic subpriority; if the operation has a * negative time to deadline, the value is (negative) time to deadline. */ virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time); /** * = Orders two dispatch entries by ascending time to deadline: returns -1 * if the first Dispatch_Entry is greater in the order, 0 if they're * equivalent, or 1 if the second Dispatch_Entry is greater in the order. */ virtual int dynamic_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); private: /// = Comparison function to pass to qsort: calls instance ()->sort_comp (). static int sort_function (void *arg1, void *arg2); /// = Instance of the strategy. static ACE_EDF_Scheduler_Strategy *instance_; }; /** * @class ACE_Criticality_Scheduler_Strategy * * @brief ACE_Criticality_Scheduler_Strategy * * Defines "schedule" method using a simple mapping directly from * operation criticality to static priority. */ class TAO_RTSched_Export ACE_Criticality_Scheduler_Strategy : public ACE_Scheduler_Strategy { public: /// = Constructor. ACE_Criticality_Scheduler_Strategy (ACE_DynScheduler::Preemption_Priority minimum_critical_priority = 0); /// = Virtual destructor. virtual ~ACE_Criticality_Scheduler_Strategy (); /// = Returns an instance of the strategy. static ACE_Criticality_Scheduler_Strategy *instance (); /** * = Compares two dispatch entries by minimum period: returns -1 if the * first Dispatch_Entry is greater in the order, 0 if they're equivalent, * or 1 if the second Dispatch_Entry is greater in the order. */ virtual int priority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); /// = Sort the dispatch entry link pointer array in descending /// criticality order. virtual void sort (Dispatch_Entry **dispatch_entries, u_int count); /// = Determine the minimum critical priority number. virtual ACE_DynScheduler::Preemption_Priority minimum_critical_priority (); /// Provide the dispatching queue type for the given dispatch entry. virtual ACE_DynScheduler::Dispatching_Type dispatch_type (const Dispatch_Entry &entry); protected: /// = Just returns 0: all operations have /// the same dynamic subpriority value. virtual long dynamic_subpriority (Dispatch_Entry &entry, RtecScheduler::Time current_time); /// = All dispatches in a given priority level have the same dynamic /// subpriority under this strategy: just returns 0. virtual int dynamic_subpriority_comp (const Dispatch_Entry &first_entry, const Dispatch_Entry &second_entry); private: /// = Comparison function to pass to qsort: calls instance ()->sort_comp (). static int sort_function (void *arg1, void *arg2); /// = Instance of the strategy. static ACE_Criticality_Scheduler_Strategy *instance_; }; TAO_END_VERSIONED_NAMESPACE_DECL #include /**/ "ace/post.h" #endif /* STRATEGY_SCHEDULER_H */ // EOF