job scheduler works with run once and run periodic schedules. Stop logic is not fully thought through.

Dependencies:   LinkedList

Dependents:   JobSchedulerDemo Borsch

Committer:
sgnezdov
Date:
Wed Aug 02 19:44:44 2017 +0000
Revision:
14:a30cc783ae89
Parent:
13:6be67ee77861
Child:
15:6b8fa5dff770
rolled back GetList

Who changed what in which revision?

UserRevisionLine numberNew 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 0:806403f3d0d1 14 /**
sgnezdov 0:806403f3d0d1 15 Declares concept of the schedule.
sgnezdov 0:806403f3d0d1 16 For example, run once, run periodically, run at the top of the hour,
sgnezdov 0:806403f3d0d1 17 never run, run weekly, monthly, etc.
sgnezdov 0:806403f3d0d1 18 */
sgnezdov 0:806403f3d0d1 19 class ISchedule {
sgnezdov 0:806403f3d0d1 20 public:
sgnezdov 2:9bf5366ad5a2 21
sgnezdov 2:9bf5366ad5a2 22 virtual ~ISchedule() {};
sgnezdov 2:9bf5366ad5a2 23
sgnezdov 2:9bf5366ad5a2 24 /**
sgnezdov 2:9bf5366ad5a2 25 NextRunTime returns next run time or zero if never.
sgnezdov 2:9bf5366ad5a2 26
sgnezdov 2:9bf5366ad5a2 27 @param from reflects current time.
sgnezdov 2:9bf5366ad5a2 28 Test cases may manipulate the value of from to test algorithms.
sgnezdov 2:9bf5366ad5a2 29
sgnezdov 2:9bf5366ad5a2 30 If return time is less than from, then scheduler will run the job
sgnezdov 2:9bf5366ad5a2 31 ASAP.
sgnezdov 2:9bf5366ad5a2 32
sgnezdov 2:9bf5366ad5a2 33 If return time is more than from, then scheduler will run the job
sgnezdov 2:9bf5366ad5a2 34 in the future calculated as (return_value - from).
sgnezdov 2:9bf5366ad5a2 35 */
sgnezdov 2:9bf5366ad5a2 36 virtual time_t NextRunTime(time_t from) = 0;
sgnezdov 2:9bf5366ad5a2 37 };
sgnezdov 2:9bf5366ad5a2 38
sgnezdov 2:9bf5366ad5a2 39 struct IJobData {
sgnezdov 2:9bf5366ad5a2 40 public:
sgnezdov 2:9bf5366ad5a2 41 virtual ~IJobData() = 0;
sgnezdov 0:806403f3d0d1 42 };
sgnezdov 0:806403f3d0d1 43
sgnezdov 1:ec6a1d054065 44 /**
sgnezdov 1:ec6a1d054065 45 ResBase provide common properties for Scheduler response queue.
sgnezdov 1:ec6a1d054065 46 */
sgnezdov 1:ec6a1d054065 47 struct ResBase {
sgnezdov 0:806403f3d0d1 48 Error error;
sgnezdov 1:ec6a1d054065 49 ResBase(Error err) : error(err) {}
sgnezdov 0:806403f3d0d1 50 };
sgnezdov 0:806403f3d0d1 51
sgnezdov 1:ec6a1d054065 52 template<typename T>
sgnezdov 1:ec6a1d054065 53 struct Response : ResBase {
sgnezdov 3:f08f55827736 54 T data;
sgnezdov 3:f08f55827736 55 Response(Error anError, T aData) : ResBase(anError), data(aData) {}
sgnezdov 1:ec6a1d054065 56 };
sgnezdov 1:ec6a1d054065 57
sgnezdov 0:806403f3d0d1 58 struct Action {
sgnezdov 0:806403f3d0d1 59 ActionType type;
sgnezdov 1:ec6a1d054065 60 Queue<ResBase, 1> resQueue;
sgnezdov 1:ec6a1d054065 61 Action(ActionType t): type(t) {}
sgnezdov 0:806403f3d0d1 62 };
sgnezdov 0:806403f3d0d1 63
sgnezdov 0:806403f3d0d1 64 /**
sgnezdov 2:9bf5366ad5a2 65 Job describes the job, its parameters and schedule.
sgnezdov 0:806403f3d0d1 66 */
sgnezdov 0:806403f3d0d1 67 class Job {
sgnezdov 0:806403f3d0d1 68 public:
sgnezdov 0:806403f3d0d1 69
sgnezdov 2:9bf5366ad5a2 70 Job(JobTypeID typeID, ISchedule *schedule, IJobData *data)
sgnezdov 3:f08f55827736 71 : _id(0), _typeID(typeID), _schedule(schedule), _data(data) {}
sgnezdov 0:806403f3d0d1 72
sgnezdov 0:806403f3d0d1 73 JobID GetID() const {
sgnezdov 0:806403f3d0d1 74 return _id;
sgnezdov 3:f08f55827736 75 }
sgnezdov 0:806403f3d0d1 76
sgnezdov 2:9bf5366ad5a2 77 void Init(JobID id) {
sgnezdov 2:9bf5366ad5a2 78 _id = id;
sgnezdov 2:9bf5366ad5a2 79 }
sgnezdov 2:9bf5366ad5a2 80
sgnezdov 1:ec6a1d054065 81 JobTypeID GetTypeID() const {
sgnezdov 0:806403f3d0d1 82 return _typeID;
sgnezdov 3:f08f55827736 83 }
sgnezdov 3:f08f55827736 84
sgnezdov 3:f08f55827736 85 ISchedule *GetSchedule() {
sgnezdov 3:f08f55827736 86 return _schedule;
sgnezdov 3:f08f55827736 87 }
sgnezdov 0:806403f3d0d1 88
sgnezdov 0:806403f3d0d1 89 private:
sgnezdov 0:806403f3d0d1 90 JobID _id;
sgnezdov 1:ec6a1d054065 91 JobTypeID _typeID;
sgnezdov 2:9bf5366ad5a2 92 ISchedule *_schedule;
sgnezdov 2:9bf5366ad5a2 93 IJobData *_data;
sgnezdov 0:806403f3d0d1 94 };
sgnezdov 0:806403f3d0d1 95
sgnezdov 2:9bf5366ad5a2 96 class Appointment {
sgnezdov 2:9bf5366ad5a2 97
sgnezdov 2:9bf5366ad5a2 98 public:
sgnezdov 2:9bf5366ad5a2 99
sgnezdov 2:9bf5366ad5a2 100 Appointment(JobTypeID typeID, ISchedule *schedule, IJobData *data, time_t time)
sgnezdov 2:9bf5366ad5a2 101 : _job(typeID, schedule, data), _time(time) { }
sgnezdov 2:9bf5366ad5a2 102
sgnezdov 2:9bf5366ad5a2 103 time_t GetTime() {
sgnezdov 2:9bf5366ad5a2 104 return _time;
sgnezdov 2:9bf5366ad5a2 105 }
sgnezdov 2:9bf5366ad5a2 106
sgnezdov 3:f08f55827736 107 void SetTime(time_t time) {
sgnezdov 3:f08f55827736 108 _time = time;
sgnezdov 3:f08f55827736 109 }
sgnezdov 3:f08f55827736 110
sgnezdov 2:9bf5366ad5a2 111 Job* GetJob() {
sgnezdov 2:9bf5366ad5a2 112 return &_job;
sgnezdov 2:9bf5366ad5a2 113 }
sgnezdov 2:9bf5366ad5a2 114
sgnezdov 2:9bf5366ad5a2 115 private:
sgnezdov 2:9bf5366ad5a2 116
sgnezdov 2:9bf5366ad5a2 117 Job _job;
sgnezdov 2:9bf5366ad5a2 118 time_t _time;
sgnezdov 2:9bf5366ad5a2 119 };
sgnezdov 2:9bf5366ad5a2 120
sgnezdov 0:806403f3d0d1 121 /**
sgnezdov 0:806403f3d0d1 122 Scheduler is responsible for maintaining job schedules and running jobs
sgnezdov 0:806403f3d0d1 123 in a serial manner. For example, next job appointments can be:
sgnezdov 0:806403f3d0d1 124 14:05, 14:05, 15:00, 16:00 and scheduler will run jobs even one after
sgnezdov 0:806403f3d0d1 125 another even if job run times collide.
sgnezdov 0:806403f3d0d1 126
sgnezdov 0:806403f3d0d1 127 The scheduler has no means of stopping running job.
sgnezdov 0:806403f3d0d1 128
sgnezdov 0:806403f3d0d1 129 The order of execution is preserved if job runs for a long time.
sgnezdov 0:806403f3d0d1 130
sgnezdov 0:806403f3d0d1 131 */
sgnezdov 0:806403f3d0d1 132 class Scheduler {
sgnezdov 0:806403f3d0d1 133 public:
sgnezdov 0:806403f3d0d1 134 Scheduler(JobService *_jobService);
sgnezdov 0:806403f3d0d1 135
sgnezdov 0:806403f3d0d1 136 void Start();
sgnezdov 0:806403f3d0d1 137 void Stop();
sgnezdov 0:806403f3d0d1 138 void WaitToStop();
sgnezdov 0:806403f3d0d1 139
sgnezdov 0:806403f3d0d1 140 /** JobAdd adds job of typeID and returns ID of added job. */
sgnezdov 2:9bf5366ad5a2 141 Response<JobID> JobAdd(JobTypeID typeID, ISchedule *schedule, IJobData *data);
sgnezdov 2:9bf5366ad5a2 142 void JobRemove(JobID jobID);
sgnezdov 14:a30cc783ae89 143 //LinkedList<Job> JobList();
sgnezdov 0:806403f3d0d1 144 private:
sgnezdov 0:806403f3d0d1 145 static void updateAdapter(void *target);
sgnezdov 0:806403f3d0d1 146 void updateHandler();
sgnezdov 4:78bcd5a675e1 147
sgnezdov 4:78bcd5a675e1 148 static void runAdapter(void *target);
sgnezdov 4:78bcd5a675e1 149 void runHandler();
sgnezdov 1:ec6a1d054065 150
sgnezdov 5:d8f69ac330f2 151 Response<JobID> reschedule(Appointment *apt);
sgnezdov 5:d8f69ac330f2 152
sgnezdov 0:806403f3d0d1 153 void process(Action *action);
sgnezdov 3:f08f55827736 154 void onWakeOnce();
sgnezdov 0:806403f3d0d1 155 private:
sgnezdov 0:806403f3d0d1 156 Thread _updater;
sgnezdov 7:98c8b2eabea3 157 bool _quitUpdater;
sgnezdov 7:98c8b2eabea3 158 /** _updates contains incoming actions for _updater */
sgnezdov 7:98c8b2eabea3 159 Queue<Action, 5> _updates;
sgnezdov 7:98c8b2eabea3 160
sgnezdov 4:78bcd5a675e1 161 Thread _runner;
sgnezdov 7:98c8b2eabea3 162 bool _quitRunner;
sgnezdov 7:98c8b2eabea3 163 /** _runs contains Appointments for _runner to execute. */
sgnezdov 7:98c8b2eabea3 164 Queue<Appointment, 5> _runs;
sgnezdov 7:98c8b2eabea3 165
sgnezdov 0:806403f3d0d1 166 JobService *_jobService;
sgnezdov 0:806403f3d0d1 167 JobID _nextJobID;
sgnezdov 3:f08f55827736 168 LinkedList<Appointment> _timeline;
sgnezdov 0:806403f3d0d1 169 };
sgnezdov 0:806403f3d0d1 170 }