job scheduler works with run once and run periodic schedules. Stop logic is not fully thought through.
Dependents: JobSchedulerDemo Borsch
scheduler.h@2:9bf5366ad5a2, 2017-07-11 (annotated)
- Committer:
- sgnezdov
- Date:
- Tue Jul 11 20:35:19 2017 +0000
- Revision:
- 2:9bf5366ad5a2
- Parent:
- 1:ec6a1d054065
- Child:
- 3:f08f55827736
improved scheduler organization
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sgnezdov | 0:806403f3d0d1 | 1 | #pragma once |
sgnezdov | 0:806403f3d0d1 | 2 | |
sgnezdov | 0:806403f3d0d1 | 3 | #include "mbed.h" |
sgnezdov | 0:806403f3d0d1 | 4 | #include "LinkedList.h" |
sgnezdov | 0:806403f3d0d1 | 5 | #include "jobService.h" |
sgnezdov | 0:806403f3d0d1 | 6 | |
sgnezdov | 0:806403f3d0d1 | 7 | namespace JobScheduler { |
sgnezdov | 0:806403f3d0d1 | 8 | |
sgnezdov | 0:806403f3d0d1 | 9 | typedef int JobID; |
sgnezdov | 1:ec6a1d054065 | 10 | typedef int JobTypeID; |
sgnezdov | 2:9bf5366ad5a2 | 11 | |
sgnezdov | 0:806403f3d0d1 | 12 | typedef int ActionType; |
sgnezdov | 0:806403f3d0d1 | 13 | |
sgnezdov | 1:ec6a1d054065 | 14 | const ActionType JobAddAT(1); |
sgnezdov | 0:806403f3d0d1 | 15 | |
sgnezdov | 0:806403f3d0d1 | 16 | /** |
sgnezdov | 0:806403f3d0d1 | 17 | Declares concept of the schedule. |
sgnezdov | 0:806403f3d0d1 | 18 | For example, run once, run periodically, run at the top of the hour, |
sgnezdov | 0:806403f3d0d1 | 19 | never run, run weekly, monthly, etc. |
sgnezdov | 0:806403f3d0d1 | 20 | */ |
sgnezdov | 0:806403f3d0d1 | 21 | class ISchedule { |
sgnezdov | 0:806403f3d0d1 | 22 | public: |
sgnezdov | 2:9bf5366ad5a2 | 23 | |
sgnezdov | 2:9bf5366ad5a2 | 24 | virtual ~ISchedule() {}; |
sgnezdov | 2:9bf5366ad5a2 | 25 | |
sgnezdov | 2:9bf5366ad5a2 | 26 | /** |
sgnezdov | 2:9bf5366ad5a2 | 27 | NextRunTime returns next run time or zero if never. |
sgnezdov | 2:9bf5366ad5a2 | 28 | |
sgnezdov | 2:9bf5366ad5a2 | 29 | @param from reflects current time. |
sgnezdov | 2:9bf5366ad5a2 | 30 | Test cases may manipulate the value of from to test algorithms. |
sgnezdov | 2:9bf5366ad5a2 | 31 | |
sgnezdov | 2:9bf5366ad5a2 | 32 | If return time is less than from, then scheduler will run the job |
sgnezdov | 2:9bf5366ad5a2 | 33 | ASAP. |
sgnezdov | 2:9bf5366ad5a2 | 34 | |
sgnezdov | 2:9bf5366ad5a2 | 35 | If return time is more than from, then scheduler will run the job |
sgnezdov | 2:9bf5366ad5a2 | 36 | in the future calculated as (return_value - from). |
sgnezdov | 2:9bf5366ad5a2 | 37 | */ |
sgnezdov | 2:9bf5366ad5a2 | 38 | virtual time_t NextRunTime(time_t from) = 0; |
sgnezdov | 2:9bf5366ad5a2 | 39 | }; |
sgnezdov | 2:9bf5366ad5a2 | 40 | |
sgnezdov | 2:9bf5366ad5a2 | 41 | struct IJobData { |
sgnezdov | 2:9bf5366ad5a2 | 42 | public: |
sgnezdov | 2:9bf5366ad5a2 | 43 | virtual ~IJobData() = 0; |
sgnezdov | 0:806403f3d0d1 | 44 | }; |
sgnezdov | 0:806403f3d0d1 | 45 | |
sgnezdov | 1:ec6a1d054065 | 46 | /** |
sgnezdov | 1:ec6a1d054065 | 47 | ResBase provide common properties for Scheduler response queue. |
sgnezdov | 1:ec6a1d054065 | 48 | */ |
sgnezdov | 1:ec6a1d054065 | 49 | struct ResBase { |
sgnezdov | 0:806403f3d0d1 | 50 | Error error; |
sgnezdov | 1:ec6a1d054065 | 51 | ResBase(Error err) : error(err) {} |
sgnezdov | 0:806403f3d0d1 | 52 | }; |
sgnezdov | 0:806403f3d0d1 | 53 | |
sgnezdov | 1:ec6a1d054065 | 54 | template<typename T> |
sgnezdov | 1:ec6a1d054065 | 55 | struct Response : ResBase { |
sgnezdov | 1:ec6a1d054065 | 56 | T Data; |
sgnezdov | 1:ec6a1d054065 | 57 | Response(Error err, T data) : ResBase(err), Data(data) {} |
sgnezdov | 1:ec6a1d054065 | 58 | }; |
sgnezdov | 1:ec6a1d054065 | 59 | |
sgnezdov | 0:806403f3d0d1 | 60 | struct Action { |
sgnezdov | 0:806403f3d0d1 | 61 | ActionType type; |
sgnezdov | 1:ec6a1d054065 | 62 | Queue<ResBase, 1> resQueue; |
sgnezdov | 1:ec6a1d054065 | 63 | Action(ActionType t): type(t) {} |
sgnezdov | 0:806403f3d0d1 | 64 | }; |
sgnezdov | 0:806403f3d0d1 | 65 | |
sgnezdov | 0:806403f3d0d1 | 66 | /** |
sgnezdov | 2:9bf5366ad5a2 | 67 | Job describes the job, its parameters and schedule. |
sgnezdov | 0:806403f3d0d1 | 68 | */ |
sgnezdov | 0:806403f3d0d1 | 69 | class Job { |
sgnezdov | 0:806403f3d0d1 | 70 | public: |
sgnezdov | 0:806403f3d0d1 | 71 | |
sgnezdov | 2:9bf5366ad5a2 | 72 | Job(JobTypeID typeID, ISchedule *schedule, IJobData *data) |
sgnezdov | 2:9bf5366ad5a2 | 73 | : _id(0), _typeID(typeID), _schedule(schedule), _data(data) {}; |
sgnezdov | 0:806403f3d0d1 | 74 | |
sgnezdov | 0:806403f3d0d1 | 75 | JobID GetID() const { |
sgnezdov | 0:806403f3d0d1 | 76 | return _id; |
sgnezdov | 0:806403f3d0d1 | 77 | }; |
sgnezdov | 0:806403f3d0d1 | 78 | |
sgnezdov | 2:9bf5366ad5a2 | 79 | void Init(JobID id) { |
sgnezdov | 2:9bf5366ad5a2 | 80 | _id = id; |
sgnezdov | 2:9bf5366ad5a2 | 81 | } |
sgnezdov | 2:9bf5366ad5a2 | 82 | |
sgnezdov | 1:ec6a1d054065 | 83 | JobTypeID GetTypeID() const { |
sgnezdov | 0:806403f3d0d1 | 84 | return _typeID; |
sgnezdov | 0:806403f3d0d1 | 85 | }; |
sgnezdov | 0:806403f3d0d1 | 86 | |
sgnezdov | 0:806403f3d0d1 | 87 | private: |
sgnezdov | 0:806403f3d0d1 | 88 | JobID _id; |
sgnezdov | 1:ec6a1d054065 | 89 | JobTypeID _typeID; |
sgnezdov | 2:9bf5366ad5a2 | 90 | ISchedule *_schedule; |
sgnezdov | 2:9bf5366ad5a2 | 91 | IJobData *_data; |
sgnezdov | 0:806403f3d0d1 | 92 | }; |
sgnezdov | 0:806403f3d0d1 | 93 | |
sgnezdov | 2:9bf5366ad5a2 | 94 | class Appointment { |
sgnezdov | 2:9bf5366ad5a2 | 95 | |
sgnezdov | 2:9bf5366ad5a2 | 96 | public: |
sgnezdov | 2:9bf5366ad5a2 | 97 | |
sgnezdov | 2:9bf5366ad5a2 | 98 | Appointment(JobTypeID typeID, ISchedule *schedule, IJobData *data, time_t time) |
sgnezdov | 2:9bf5366ad5a2 | 99 | : _job(typeID, schedule, data), _time(time) { } |
sgnezdov | 2:9bf5366ad5a2 | 100 | |
sgnezdov | 2:9bf5366ad5a2 | 101 | time_t GetTime() { |
sgnezdov | 2:9bf5366ad5a2 | 102 | return _time; |
sgnezdov | 2:9bf5366ad5a2 | 103 | } |
sgnezdov | 2:9bf5366ad5a2 | 104 | |
sgnezdov | 2:9bf5366ad5a2 | 105 | Job* GetJob() { |
sgnezdov | 2:9bf5366ad5a2 | 106 | return &_job; |
sgnezdov | 2:9bf5366ad5a2 | 107 | } |
sgnezdov | 2:9bf5366ad5a2 | 108 | |
sgnezdov | 2:9bf5366ad5a2 | 109 | private: |
sgnezdov | 2:9bf5366ad5a2 | 110 | |
sgnezdov | 2:9bf5366ad5a2 | 111 | Job _job; |
sgnezdov | 2:9bf5366ad5a2 | 112 | time_t _time; |
sgnezdov | 2:9bf5366ad5a2 | 113 | }; |
sgnezdov | 2:9bf5366ad5a2 | 114 | |
sgnezdov | 0:806403f3d0d1 | 115 | /** |
sgnezdov | 0:806403f3d0d1 | 116 | Scheduler is responsible for maintaining job schedules and running jobs |
sgnezdov | 0:806403f3d0d1 | 117 | in a serial manner. For example, next job appointments can be: |
sgnezdov | 0:806403f3d0d1 | 118 | 14:05, 14:05, 15:00, 16:00 and scheduler will run jobs even one after |
sgnezdov | 0:806403f3d0d1 | 119 | another even if job run times collide. |
sgnezdov | 0:806403f3d0d1 | 120 | |
sgnezdov | 0:806403f3d0d1 | 121 | The scheduler has no means of stopping running job. |
sgnezdov | 0:806403f3d0d1 | 122 | |
sgnezdov | 0:806403f3d0d1 | 123 | The order of execution is preserved if job runs for a long time. |
sgnezdov | 0:806403f3d0d1 | 124 | |
sgnezdov | 0:806403f3d0d1 | 125 | */ |
sgnezdov | 0:806403f3d0d1 | 126 | class Scheduler { |
sgnezdov | 0:806403f3d0d1 | 127 | public: |
sgnezdov | 0:806403f3d0d1 | 128 | Scheduler(JobService *_jobService); |
sgnezdov | 0:806403f3d0d1 | 129 | |
sgnezdov | 0:806403f3d0d1 | 130 | void Start(); |
sgnezdov | 0:806403f3d0d1 | 131 | void Stop(); |
sgnezdov | 0:806403f3d0d1 | 132 | void WaitToStop(); |
sgnezdov | 0:806403f3d0d1 | 133 | |
sgnezdov | 0:806403f3d0d1 | 134 | /** JobAdd adds job of typeID and returns ID of added job. */ |
sgnezdov | 2:9bf5366ad5a2 | 135 | Response<JobID> JobAdd(JobTypeID typeID, ISchedule *schedule, IJobData *data); |
sgnezdov | 2:9bf5366ad5a2 | 136 | void JobRemove(JobID jobID); |
sgnezdov | 0:806403f3d0d1 | 137 | private: |
sgnezdov | 0:806403f3d0d1 | 138 | static void updateAdapter(void *target); |
sgnezdov | 0:806403f3d0d1 | 139 | void updateHandler(); |
sgnezdov | 1:ec6a1d054065 | 140 | |
sgnezdov | 0:806403f3d0d1 | 141 | void process(Action *action); |
sgnezdov | 0:806403f3d0d1 | 142 | private: |
sgnezdov | 0:806403f3d0d1 | 143 | Thread _updater; |
sgnezdov | 0:806403f3d0d1 | 144 | bool _quit; |
sgnezdov | 0:806403f3d0d1 | 145 | JobService *_jobService; |
sgnezdov | 0:806403f3d0d1 | 146 | JobID _nextJobID; |
sgnezdov | 0:806403f3d0d1 | 147 | /** _actions contains incoming action queue to handle. */ |
sgnezdov | 0:806403f3d0d1 | 148 | Queue<Action, 5> _actions; |
sgnezdov | 2:9bf5366ad5a2 | 149 | LinkedList<Appointment> _timeline; |
sgnezdov | 0:806403f3d0d1 | 150 | |
sgnezdov | 0:806403f3d0d1 | 151 | }; |
sgnezdov | 0:806403f3d0d1 | 152 | } |