Advertisement
Guest User

TinyScheduler ver.6

a guest
Feb 28th, 2017
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.67 KB | None | 0 0
  1. /*
  2.  * TaskScheduler.hpp
  3.  *
  4.  * Created: 16.11.2015 3:44:02
  5.  *  Author: dx
  6.  
  7.  * Very simple tiny task scheduler designed with minimal overhead in mind
  8.  * You pay for what you are using only!
  9.  * General use case with default settings:
  10.  *   TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService > TaskScheduler;
  11.  
  12.  * Defaults:
  13.  *  timer resolution 8Bit                               Timer8Bit
  14.  *  task disable feature is turned off                  TaskDisable_OFF
  15.  *  task timers are NOT reloaded in constructor!        use TS_RELOAD_ON_CONSTRUCT or ReloadAllTaskTimers()
  16.                                                         Usually not a problem, see description below!                                          
  17.  
  18.  * MakeTasklist<Task1, Task2, TaskN> supports up to 16 tasks
  19.  
  20.  
  21.  * Task must be a class with _STATIC_ uint32_t Period and _STATIC_ Run() func
  22.  * static is required!
  23.  * You may optionally add other functions and variables - this will have no effect on scheduler's work
  24. struct task1
  25. {
  26.     static const uint32_t Period = 22;
  27.     static void Run()
  28.     {   //this is non member function call
  29.         Task1_func();
  30.          
  31.         //also you may call some instance func
  32.         //SomeClass.Foo();
  33.        
  34.         //you may implement task code right here if you want
  35.         //PORTB |= (1<< PINB3);
  36.     }
  37. };
  38.  
  39.  
  40.  * TimerService provides time(timer ticks to the scheduler)
  41.  * Implement as class with static method uint32_t GetTickCount()
  42.  struct TimeService
  43.  {
  44.      static uint32_t GetTickCount()
  45.      {
  46.          return G_TimerTicks; //returning a global tick counter, but you can return hardware counter - no problem.
  47.      };
  48.  };
  49.  
  50.  
  51.  * Timer resolution: Timer8Bit, Timer16Bit or Timer32Bit
  52.  *   TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService, Timer32Bit > TaskScheduler;
  53.  
  54.  
  55.  * Task disable feature TaskDisable_ON TaskDisable_OFF
  56.  *   TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService, Timer8Bit, TaskDisable_ON > TaskScheduler;
  57.  *   TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerServicem Timer8Bit, TaskDisable_OFF > TaskScheduler; //also valid code
  58.  
  59.  * NOTE:
  60.  * By default timers[] are NOT explicitly initialized in constructor.
  61.  * Usually TaskScheduler instant is a global variable(i.e. has static duration) and all timers will be initialized by 0
  62.  * which means, if your TimerService is also global and starts count from 0 - everything is fine!!!
  63.  *
  64.  * You may pass TS_RELOAD_ON_CONSTRUCT to constructor to make timers reload on instantiation:
  65.  *   TinyScheduler< MakeTasklist<Task1, Task2, TaskN>, TimerService > TaskScheduler( TS_RELOAD_ON_CONSTRUCT );
  66.  * or call somewhere:
  67.  *   TaskScheduler.ReloadAllTaskTimers(); //preferred way of doing timer initialization. Costs less Flash bytes.
  68.  * TS_RELOAD_ON_CONSTRUCT will cost you more Flash bytes! Don't know why constructor is so heavy.  
  69. */
  70.  
  71. #include <stdint.h>
  72. #include "loki/Typelist.h"
  73. #include "loki/TypeManip.h"
  74.  
  75. #ifndef TASKSCHEDULER_H_
  76. #define TASKSCHEDULER_H_   
  77.    
  78. //encapsulates Loki library for end user
  79. //Use as follows:
  80. //TinyScheduler< MakeTasklist<Task1, Task2, TaskN> > TaskScheduler;
  81. template<   typename T1  = Loki::NullType, typename T2  = Loki::NullType, typename T3  = Loki::NullType,
  82.             typename T4  = Loki::NullType, typename T5  = Loki::NullType, typename T6  = Loki::NullType,
  83.             typename T7  = Loki::NullType, typename T8  = Loki::NullType, typename T9  = Loki::NullType,
  84.             typename T10 = Loki::NullType, typename T11 = Loki::NullType, typename T12 = Loki::NullType,
  85.             typename T13 = Loki::NullType, typename T14 = Loki::NullType, typename T15 = Loki::NullType,
  86.             typename T16 = Loki::NullType >
  87. struct MakeTasklist {
  88.     typedef typename Loki::TL::MakeTypelist<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::Result Result;
  89. };
  90. template<> struct MakeTasklist<>{ typedef typename Loki::TL::MakeTypelist<>::Result Result; };
  91.  
  92. //use this flag to tell constructor do ReloadAllTimers() on scheduler instantiation
  93. enum{TS_RELOAD_ON_CONSTRUCT};
  94.  
  95. //TimerResolution template param
  96. struct Timer8Bit{ typedef uint8_t TimerType; };
  97. struct Timer16Bit{ typedef uint16_t TimerType; };
  98. struct Timer32Bit{ typedef uint32_t TimerType; };
  99.  
  100. //TaskDisableFeature template param
  101. struct TaskDisable_ON{};
  102. struct TaskDisable_OFF{};
  103.        
  104. //To enable empty base optimization TaskDisable feature is moved to dedicated class
  105. //empty base optimization gives us 1 byte RAM when TaskDisableFeature is turned off
  106. //Dummy methods are also static to allow completely optimize them away.
  107. template<typename TList, typename TaskDisableFeature> class TaskDisableImplementation;
  108. template<typename TList>
  109. class TaskDisableImplementation<TList, TaskDisable_OFF>
  110. {  
  111. protected:
  112.     static bool IsTaskEnabled_impl(const int& i){return true;}
  113.     static void TaskDisable_impl(const int& i){}
  114.     static void TaskEnable_impl(const int& i){}
  115. };
  116. template<typename TList>
  117. class TaskDisableImplementation<TList, TaskDisable_ON>
  118. {
  119. protected:
  120.     bool IsTaskEnabled_impl(const int& i){ return !( TaskDisableMask & (1 << i) ); }
  121.     void TaskDisable_impl(const int& i){ TaskDisableMask |= 1 << i; }
  122.     void TaskEnable_impl(const int& i){  TaskDisableMask &= ~(1 << i); }
  123. private:   
  124.     static const int TaskListLen = Loki::TL::Length< typename TList::Result >::value;              
  125.     //select type depending on task list length. To support task list of up to 16 tasks
  126.     typename Loki::Select< (TaskListLen > 8), uint16_t, uint8_t >::Result TaskDisableMask;
  127. };
  128.  
  129. template< typename TList, typename TimeService, typename TimerResolution=Timer8Bit,
  130. typename TaskDisableFeature=TaskDisable_OFF>
  131. class TinyScheduler : TaskDisableImplementation<TList, TaskDisableFeature>
  132. {
  133.     typedef TaskDisableImplementation<TList, TaskDisableFeature> BaseClass;
  134. public:    
  135.     TinyScheduler() {};
  136.    
  137.     //this will fire up on TS_RELOAD_ON_CONSTRUCT
  138.     TinyScheduler(const int&){ ReloadAllTaskTimers(); };
  139.  
  140.     void RunScheduled(){ RunScheduled_imp( Loki::Int2Type<TaskListLen-1>(), TimeService::GetTickCount() ); }
  141.    
  142.     template<typename T>
  143.     void TaskDisable(const T&){ BaseClass::TaskDisable_impl( Loki::TL::IndexOf<TaskList, T>::value ); }
  144.    
  145.     template<typename T>
  146.     void TaskEnable(const T&){  BaseClass::TaskEnable_impl( Loki::TL::IndexOf<TaskList, T>::value ); }
  147.    
  148.     template<typename T>
  149.     void ReloadTaskTimer(const T&){ timers[ Loki::TL::IndexOf<TaskList, T>::value ] = TimeService::GetTickCount(); }
  150.        
  151.     void ReloadAllTaskTimers(){ ReloadAll_impl( Loki::Int2Type<TaskListLen-1>(), TimeService::GetTickCount() ); }              
  152. private:
  153.     typedef typename TList::Result TaskList;
  154.     static const int TaskListLen = Loki::TL::Length< TaskList >::value;
  155.    
  156.     typedef typename TimerResolution::TimerType TimerT;
  157.     TimerT timers[TaskListLen];
  158.    
  159.     TinyScheduler(const TinyScheduler&);
  160.     TinyScheduler& operator=(const TinyScheduler&);
  161.    
  162.     //recursive iteration over TaskList and reload task timers
  163.     template<int I>
  164.     void ReloadAll_impl(Loki::Int2Type<I>, const TimerT& nowTicks)
  165.     {
  166.         ReloadAll_impl( Loki::Int2Type<I-1>(), nowTicks );
  167.         timers[I] = nowTicks;
  168.     }
  169.     void ReloadAll_impl(Loki::Int2Type<0>, const TimerT& nowTicks)
  170.     {
  171.         timers[0] = nowTicks;
  172.     }
  173.        
  174.     template<int I>
  175.     void RunScheduled_imp(Loki::Int2Type<I>, const TimerT& nowTicks)
  176.     {
  177.         RunScheduled_imp( Loki::Int2Type<I-1>(), nowTicks );                   
  178.         if( BaseClass::IsTaskEnabled_impl(I) )
  179.         {
  180.             typedef typename Loki::TL::TypeAt<TaskList, I>::Result Task;               
  181.             if( static_cast<TimerT>((nowTicks - timers[I])) >= Task::Period )
  182.             {
  183.                 Task::Run();
  184.                 timers[I] = TimeService::GetTickCount();
  185.             }
  186.         }
  187.     }
  188.     void RunScheduled_imp(Loki::Int2Type<0>, const TimerT& nowTicks)
  189.     {
  190.         if( BaseClass::IsTaskEnabled_impl(0) )
  191.         {
  192.             typedef typename Loki::TL::TypeAt<TaskList, 0>::Result Task;
  193.             if( static_cast<TimerT>((nowTicks - timers[0])) >= Task::Period )
  194.             {
  195.                 Task::Run();
  196.                 timers[0] = TimeService::GetTickCount();
  197.             }
  198.         }
  199.     }
  200. };
  201. #endif /* TASKSCHEDULER_H_ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement