aboutsummaryrefslogtreecommitdiff
path: root/src/minicron.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/minicron.h')
-rw-r--r--src/minicron.h226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/minicron.h b/src/minicron.h
new file mode 100644
index 0000000..b100ad0
--- /dev/null
+++ b/src/minicron.h
@@ -0,0 +1,226 @@
1#ifndef BU_MINICRON_H
2#define BU_MINICRON_H
3
4#include "bu/signals.h"
5#include "bu/heap.h"
6#include "bu/fstring.h"
7
8#include <time.h>
9
10namespace Bu
11{
12 /**
13 * A simple cron like system designed to be embedded in any program. This
14 * class creates a simple cron system that can run any number of jobs at
15 * customizable intervals or schedules. It does not support some of the
16 * more complex scheduling that some cron systems can do such as load
17 * balancing directly, but this could be done on the job side.
18 *
19 * This system is synchronous, it does not use any threads on it's own, but
20 * it is threadsafe, so a cron thread could be created if desired.
21 *
22 * The operation is fairly simple, jobs can be added at any time, and use
23 * any timer they would like, even custom timers. When it is time for a
24 * job to be run it signals the slot provided when the job was added. Every
25 * job slot recieves a handle to the job object so that it may control it's
26 * own lifetime and get information about itself. In addition, every job
27 * is assigned a unique ID that can be used to control it's operation
28 * at any time.
29 *
30 * By default a job will continually reschedule itself after being run
31 * unless it calls stop() on it's job object, it is removed using
32 * removeJob() on the cron object, or it is added with addJobOnce.
33 */
34 class MiniCron
35 {
36 public:
37 class Job;
38 class Timer;
39 typedef Bu::Signal1<void, Bu::MiniCron::Job &> CronSignal;
40 typedef int JobId;
41
42 MiniCron();
43 virtual ~MiniCron();
44
45 /**
46 * Tells you if there are jobs registered in the MiniCron.
47 *@returns true if there are jobs, false otherwise.
48 */
49 virtual bool hasJobs();
50
51 /**
52 * If there are jobs, tells you the time the next one will execute.
53 *@returns The timestamp that the next job will execute at.
54 */
55 virtual time_t getNextRun();
56
57 /**
58 * Call this regularly to execute all jobs that should be executed.
59 * This will loop until all jobs who's run time match the current time
60 * or are below the current time (we've missed them).
61 * If there is nothing to run, the runtime of this funcion is constant,
62 * it is very fast. Otherwise it executes at log(N) per job run,
63 * O(N*log(N)).
64 */
65 virtual void poll();
66
67 /**
68 * Add a job for repeated scheduling. Pass in a slot to signal, and a
69 * Timer object to use to do the scheduling. This function returns a
70 * JobId which can be used at a later time to control the execution of
71 * the job.
72 */
73 virtual JobId addJob( CronSignal sigJob, const Timer &t );
74
75 /**
76 * Add a job for one time scheduling. Pass in a slot to signal, and a
77 * Timer object to use to schodule the one run of this job. This
78 * function returns a JobId which can be used at a later time to control
79 * the execution of the job.
80 */
81 virtual JobId addJobOnce( CronSignal sigJob, const Timer &t );
82
83 /**
84 * Remove a job, preventing all future runs of the job. If there is no
85 * job matching the given JobId then nothing will happen. However, this
86 * function is relatively expensive compared to the others in this class
87 * and has a worse case runtime of 2*N*log(N), still not that bad, and
88 * a O(N*log(N)).
89 */
90 virtual void removeJob( JobId jid );
91
92 class Timer
93 {
94 public:
95 Timer();
96 virtual ~Timer();
97
98 virtual time_t nextTime()=0;
99 virtual Timer *clone() const = 0;
100 };
101
102 class TimerInterval : public Timer
103 {
104 public:
105 TimerInterval( time_t tFirst, time_t tInterval );
106 virtual ~TimerInterval();
107
108 virtual time_t nextTime();
109 virtual Timer *clone() const
110 { return new TimerInterval( *this ); }
111 private:
112 time_t tNext;
113 time_t tInterval;
114 };
115
116 class TimerBasic : public Timer
117 {
118 public:
119 TimerBasic( const Bu::FString &s );
120 virtual ~TimerBasic();
121
122 virtual time_t nextTime();
123 virtual Timer *clone() const
124 { return new TimerBasic( *this ); }
125
126 private:
127 enum Token
128 {
129 tokDaily,
130 tokHourly,
131 tokWeekly,
132 tokMonthly,
133 tokYearly,
134 valInt,
135 tokErr,
136 tokEos
137 };
138 Token lex( Bu::FString::const_iterator &i );
139 int lexInt( Bu::FString::const_iterator &i );
140 int iVal; //< A temp variable for parsing.
141 time_t tLast;
142 Bu::FString sSpec;
143 };
144
145 class Job
146 {
147 friend class Bu::MiniCron;
148 public:
149 Job( JobId jid, bool bRepeat=true );
150 virtual ~Job();
151
152 /**
153 * Execute this job once, increment the runcount and schedule the
154 * next occurance of it.
155 */
156 void run();
157
158 /**
159 * Get the time this job will next run.
160 */
161 time_t getNextRun();
162
163 /**
164 * Compute the time this job will next run.
165 */
166 void calcNextRun();
167
168 /**
169 * Replace the current job timer with a new one, this will trigger
170 * a re-schedule.
171 */
172 void setTimer( const Timer &t );
173
174 /**
175 * Stop execution of this job, never execute this job again.
176 */
177 void stop();
178
179 /**
180 * Undo a previous stop. This will cause a job that has been
181 * stopped or even added with addJobOnce to be set for repeated
182 * scheduling.
183 */
184 void resume();
185
186 /**
187 * Get the unique ID of this job.
188 */
189 JobId getId();
190
191 /**
192 * Get the timestamp this job was created.
193 */
194 time_t getTimeCreated();
195
196 /**
197 * Get the current run count of this job, how many times it has been
198 * executed. This is incremented before the slot is signaled.
199 */
200 int getRunCount();
201
202 private:
203 CronSignal sigJob;
204 time_t tNextRun;
205 Timer *pTimer;
206 bool bContinue;
207 JobId jid;
208 time_t tAdded;
209 int iRunCount;
210 };
211
212 private:
213 struct JobPtrCmp
214 {
215 bool operator()( const Job *pLeft, const Job *pRight )
216 {
217 return pLeft->tNextRun < pRight->tNextRun;
218 }
219 };
220 typedef Bu::Heap<Job *, JobPtrCmp> JobHeap;
221 JobHeap hJobs;
222 JobId jidNext;
223 };
224};
225
226#endif