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:
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?

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 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 }