job scheduler works with run once and run periodic schedules. Stop logic is not fully thought through.
Dependents: JobSchedulerDemo Borsch
scheduler.cpp@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 | #include "scheduler.h" |
sgnezdov | 0:806403f3d0d1 | 2 | |
sgnezdov | 0:806403f3d0d1 | 3 | void update(void *target) { |
sgnezdov | 0:806403f3d0d1 | 4 | }; |
sgnezdov | 0:806403f3d0d1 | 5 | |
sgnezdov | 0:806403f3d0d1 | 6 | namespace JobScheduler { |
sgnezdov | 1:ec6a1d054065 | 7 | |
sgnezdov | 2:9bf5366ad5a2 | 8 | bool descendingTimeline(Appointment *a1, Appointment *a2) |
sgnezdov | 2:9bf5366ad5a2 | 9 | { |
sgnezdov | 2:9bf5366ad5a2 | 10 | bool rv = a1->GetTime() <= a2->GetTime(); |
sgnezdov | 2:9bf5366ad5a2 | 11 | //printf("(%d %d:%d)", *d1, *d2, rv); |
sgnezdov | 2:9bf5366ad5a2 | 12 | return rv; |
sgnezdov | 2:9bf5366ad5a2 | 13 | }; |
sgnezdov | 2:9bf5366ad5a2 | 14 | |
sgnezdov | 2:9bf5366ad5a2 | 15 | /** |
sgnezdov | 2:9bf5366ad5a2 | 16 | JobAddReq adds new job to the scheduler. |
sgnezdov | 2:9bf5366ad5a2 | 17 | */ |
sgnezdov | 1:ec6a1d054065 | 18 | struct JobAddReq: Action { |
sgnezdov | 2:9bf5366ad5a2 | 19 | Appointment *apt; |
sgnezdov | 1:ec6a1d054065 | 20 | Response<JobID> response; |
sgnezdov | 2:9bf5366ad5a2 | 21 | JobAddReq(Appointment *a) : Action(JobAddAT), apt(a), response(NoError, 0) {} |
sgnezdov | 1:ec6a1d054065 | 22 | }; |
sgnezdov | 0:806403f3d0d1 | 23 | |
sgnezdov | 0:806403f3d0d1 | 24 | Scheduler::Scheduler(JobService *jobService) |
sgnezdov | 2:9bf5366ad5a2 | 25 | : _jobService(jobService), _nextJobID(1) { } |
sgnezdov | 0:806403f3d0d1 | 26 | |
sgnezdov | 0:806403f3d0d1 | 27 | void Scheduler::updateAdapter(void *thisPointer) { |
sgnezdov | 0:806403f3d0d1 | 28 | Scheduler *self = static_cast<Scheduler*>(thisPointer); |
sgnezdov | 0:806403f3d0d1 | 29 | self->updateHandler(); |
sgnezdov | 0:806403f3d0d1 | 30 | } |
sgnezdov | 0:806403f3d0d1 | 31 | |
sgnezdov | 0:806403f3d0d1 | 32 | void Scheduler::Start() { |
sgnezdov | 0:806403f3d0d1 | 33 | _updater.start(callback(Scheduler::updateAdapter, this)); |
sgnezdov | 0:806403f3d0d1 | 34 | } |
sgnezdov | 0:806403f3d0d1 | 35 | |
sgnezdov | 0:806403f3d0d1 | 36 | void Scheduler::Stop() { |
sgnezdov | 0:806403f3d0d1 | 37 | // it is not thread-safe, but impact is non-existent. |
sgnezdov | 0:806403f3d0d1 | 38 | _quit = true; |
sgnezdov | 0:806403f3d0d1 | 39 | } |
sgnezdov | 0:806403f3d0d1 | 40 | |
sgnezdov | 0:806403f3d0d1 | 41 | void Scheduler::WaitToStop() { |
sgnezdov | 0:806403f3d0d1 | 42 | _updater.join(); |
sgnezdov | 0:806403f3d0d1 | 43 | } |
sgnezdov | 0:806403f3d0d1 | 44 | |
sgnezdov | 2:9bf5366ad5a2 | 45 | Response<JobID> Scheduler::JobAdd(JobTypeID jobTID, ISchedule *schedule, IJobData *data) { |
sgnezdov | 2:9bf5366ad5a2 | 46 | Appointment *apt = new Appointment(jobTID, schedule, data, time_t(0)); |
sgnezdov | 2:9bf5366ad5a2 | 47 | if (NULL == apt) { |
sgnezdov | 2:9bf5366ad5a2 | 48 | printf("[Scheduler::JobAdd] failed to allocate appointment\n"); |
sgnezdov | 2:9bf5366ad5a2 | 49 | return Response<JobID>(1, 0); |
sgnezdov | 2:9bf5366ad5a2 | 50 | } |
sgnezdov | 2:9bf5366ad5a2 | 51 | JobAddReq req(apt); |
sgnezdov | 1:ec6a1d054065 | 52 | _actions.put(&req); |
sgnezdov | 0:806403f3d0d1 | 53 | // default is wait forever |
sgnezdov | 1:ec6a1d054065 | 54 | osEvent evt = req.resQueue.get(); |
sgnezdov | 0:806403f3d0d1 | 55 | if (evt.status == osEventMessage) { |
sgnezdov | 2:9bf5366ad5a2 | 56 | if (evt.value.p != NULL) { |
sgnezdov | 2:9bf5366ad5a2 | 57 | printf("[Scheduler::JobAdd] completed ok\n"); |
sgnezdov | 2:9bf5366ad5a2 | 58 | } else { |
sgnezdov | 2:9bf5366ad5a2 | 59 | printf("[Scheduler::JobAdd] NOT added (C1)\n"); |
sgnezdov | 2:9bf5366ad5a2 | 60 | } |
sgnezdov | 2:9bf5366ad5a2 | 61 | } else { |
sgnezdov | 2:9bf5366ad5a2 | 62 | // not sure what condition is |
sgnezdov | 2:9bf5366ad5a2 | 63 | printf("[Scheduler::JobAdd] NOT added (C2)\n"); |
sgnezdov | 2:9bf5366ad5a2 | 64 | delete apt; |
sgnezdov | 2:9bf5366ad5a2 | 65 | apt = NULL; |
sgnezdov | 0:806403f3d0d1 | 66 | } |
sgnezdov | 2:9bf5366ad5a2 | 67 | // yes, return a copy of the structure |
sgnezdov | 1:ec6a1d054065 | 68 | return req.response; |
sgnezdov | 0:806403f3d0d1 | 69 | } |
sgnezdov | 0:806403f3d0d1 | 70 | |
sgnezdov | 2:9bf5366ad5a2 | 71 | void Scheduler::JobRemove(JobID jobID) { |
sgnezdov | 0:806403f3d0d1 | 72 | } |
sgnezdov | 0:806403f3d0d1 | 73 | |
sgnezdov | 0:806403f3d0d1 | 74 | void Scheduler::updateHandler() { |
sgnezdov | 0:806403f3d0d1 | 75 | while (!_quit) { |
sgnezdov | 0:806403f3d0d1 | 76 | printf("[Scheduler::updateHandler] waiting for action\n"); |
sgnezdov | 0:806403f3d0d1 | 77 | // wait forever ... |
sgnezdov | 0:806403f3d0d1 | 78 | osEvent evt = _actions.get(); |
sgnezdov | 0:806403f3d0d1 | 79 | if (evt.status == osEventMessage) { |
sgnezdov | 0:806403f3d0d1 | 80 | printf("[Scheduler::updateHandler] process action\n"); |
sgnezdov | 0:806403f3d0d1 | 81 | this->process((Action*)evt.value.p); |
sgnezdov | 0:806403f3d0d1 | 82 | } else { |
sgnezdov | 0:806403f3d0d1 | 83 | printf("[Scheduler::updateHandler] NOT osEventMessage\n"); |
sgnezdov | 0:806403f3d0d1 | 84 | } |
sgnezdov | 0:806403f3d0d1 | 85 | wait(2); |
sgnezdov | 0:806403f3d0d1 | 86 | } |
sgnezdov | 0:806403f3d0d1 | 87 | } |
sgnezdov | 0:806403f3d0d1 | 88 | |
sgnezdov | 0:806403f3d0d1 | 89 | void Scheduler::process(Action *action) |
sgnezdov | 0:806403f3d0d1 | 90 | { |
sgnezdov | 1:ec6a1d054065 | 91 | switch(action->type) { |
sgnezdov | 1:ec6a1d054065 | 92 | case JobAddAT: { |
sgnezdov | 1:ec6a1d054065 | 93 | JobAddReq *req = static_cast<JobAddReq*>(action); |
sgnezdov | 2:9bf5366ad5a2 | 94 | Job *job = req->apt->GetJob(); |
sgnezdov | 2:9bf5366ad5a2 | 95 | if (job->GetID() == 0) { |
sgnezdov | 2:9bf5366ad5a2 | 96 | // assign job its ID |
sgnezdov | 2:9bf5366ad5a2 | 97 | job->Init(_nextJobID++); |
sgnezdov | 2:9bf5366ad5a2 | 98 | } |
sgnezdov | 2:9bf5366ad5a2 | 99 | node<Appointment> *tmp = _timeline.insertOrdered(req->apt, descendingTimeline); |
sgnezdov | 2:9bf5366ad5a2 | 100 | if (NULL == tmp) { |
sgnezdov | 2:9bf5366ad5a2 | 101 | printf("[Scheduler::process] timeline insert failed\n"); |
sgnezdov | 2:9bf5366ad5a2 | 102 | action->resQueue.put(NULL); |
sgnezdov | 2:9bf5366ad5a2 | 103 | return; |
sgnezdov | 2:9bf5366ad5a2 | 104 | } |
sgnezdov | 2:9bf5366ad5a2 | 105 | //printf("[Scheduler::process] simulate error\n"); |
sgnezdov | 2:9bf5366ad5a2 | 106 | //action->resQueue.put(NULL); |
sgnezdov | 1:ec6a1d054065 | 107 | action->resQueue.put(&req->response); |
sgnezdov | 1:ec6a1d054065 | 108 | break; |
sgnezdov | 1:ec6a1d054065 | 109 | } |
sgnezdov | 1:ec6a1d054065 | 110 | default: |
sgnezdov | 1:ec6a1d054065 | 111 | printf("[Scheduler::process] unknown action type\n"); |
sgnezdov | 1:ec6a1d054065 | 112 | action->resQueue.put(NULL); |
sgnezdov | 1:ec6a1d054065 | 113 | } |
sgnezdov | 0:806403f3d0d1 | 114 | } |
sgnezdov | 0:806403f3d0d1 | 115 | |
sgnezdov | 0:806403f3d0d1 | 116 | } |