2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc/timer.pmc - Timer
12 set P0[.PARROT_TIMER_SEC], I_seconds # whole seconds
13 set P0[.PARROT_TIMER_USEC], I_micro seconds # and/or micro seconds
14 set P0[.PARROT_TIMER_NSEC], N_seconds_frac # or fraction in seconds
15 set P0[.PARROT_TIMER_REPEAT], I_repeat # 0 = one shot ...
16 set P0[.PARROT_TIMER_HANDLER], P_sub # set handler sub PMC
17 invoke P0 # start timer
18 set P0[.PARROT_TIMER_RUNNING], 1 # same
20 new P0, 'Timer', P1 # set everything
22 set I0, P0[.PARROT_TIMER_SEC] # query current timer status
23 set N0, P0[.PARROT_TIMER_NSEC]
25 set P0[.PARROT_TIMER_RUNNING], 0 # turn timer off
30 This is the Timer base class
32 Running timers are kept in a linked list. Each timer has a tick count,
33 which gets decremented if the system timer expires. If the tick count
34 reaches zero, the timer handler gets invoked via Parrot's event handling
37 The Timer resolution is operating system dependent. It's only guaranteed
38 that the Timer will fire some time after the programmed interval.
40 The Timer stops after invoking the handler (repeat + 1) times. To create a
41 Timer that will run forever, set "repeat" to -1. Turning the Timer off
42 preserves set values; the Timer is not destroyed.
44 When setting both C<PARROT_TIMER_SEC> and C<PARROT_TIMER_USEC> it must
45 be done in that sequence, whole seconds first. If a timer is constructed
46 with an initializer and it should be run immediately, the
47 C<PARROT_TIMER_RUNNING> value has to be in the last key of the
58 #include "parrot/parrot.h"
59 #include "parrot/scheduler_private.h"
61 pmclass Timer extends Task provides event need_ext {
62 ATTR INTVAL id; /* The task ID. */
63 ATTR INTVAL priority; /* The priority of the task. */
64 ATTR FLOATVAL birthtime; /* The creation time stamp of the task. */
65 ATTR STRING *type; /* The type of the task. */
66 ATTR STRING *subtype; /* The subtype of the task. */
67 ATTR STRING *status; /* The status of the task. */
68 ATTR Parrot_Interp interp; /* The interpreter that created the task. */
69 ATTR PMC *codeblock; /* An (optional) codeblock for the task. */
70 ATTR PMC *data; /* Additional data for the task. */
71 ATTR char *cb_data; /* Additional data for a callback event. */
72 ATTR FLOATVAL duration; /* The duration of the timer pause */
73 ATTR FLOATVAL interval; /* How often to repeat */
74 ATTR INTVAL repeat; /* Whether to repeat:
75 * 0 = run once (no repeat), -1 = forever */
81 Initializes the timer.
88 Parrot_Timer * const core_struct = mem_allocate_zeroed_typed(Parrot_Timer);
90 /* Set flags for custom DOD mark and destroy. */
91 PObj_custom_mark_SET(SELF);
92 PObj_active_destroy_SET(SELF);
94 /* Set up the core struct. */
95 PMC_data(SELF) = core_struct;
97 core_struct->type = CONST_STRING(interp, "timer");
98 core_struct->subtype = CONST_STRING(interp, "");
99 core_struct->priority = 0;
100 core_struct->status = CONST_STRING(interp, "created");
101 core_struct->birthtime = 0.0;
102 core_struct->codeblock = PMCNULL;
103 core_struct->interp = INTERP;
104 core_struct->duration = 0.0;
105 core_struct->interval = 0.0;
106 core_struct->repeat = 0;
108 /* Make sure the flag is cleared by default */
109 TASK_terminate_runloop_CLEAR(SELF);
114 =item C<void init_pmc(PMC *init)>
116 See F<docs/pdds/pdd02_vtables.pod> for initializers.
122 VTABLE void init_pmc(PMC *init) {
123 const INTVAL n = VTABLE_get_integer(INTERP, init);
128 for (i = 0; i < n; i += 2) {
129 const INTVAL key = VTABLE_get_integer_keyed_int(INTERP, init, i);
131 case PARROT_TIMER_SEC:
132 case PARROT_TIMER_USEC:
133 case PARROT_TIMER_REPEAT:
134 case PARROT_TIMER_RUNNING:
136 const INTVAL val = VTABLE_get_integer_keyed_int(INTERP, init, i+1);
137 SELF.set_integer_keyed_int(key, val);
140 case PARROT_TIMER_NSEC:
142 const FLOATVAL nval = VTABLE_get_number_keyed_int(INTERP, init, i+1);
143 SELF.set_number_keyed_int(key, nval);
146 case PARROT_TIMER_HANDLER:
148 PMC * const pval = VTABLE_get_pmc_keyed_int(INTERP, init, i+1);
149 SELF.set_pmc_keyed_int(key, pval);
160 =item C<PMC *clone()>
162 Create a copy of the timer, resetting status, id, and birthtime.
168 VTABLE PMC *clone() {
169 PMC * const copy = SUPER();
170 Parrot_Timer * const new_struct = PARROT_TIMER(copy);
171 Parrot_Timer * const old_struct = PARROT_TIMER(SELF);
173 new_struct->duration = old_struct->duration;
174 new_struct->interval = old_struct->interval;
175 new_struct->repeat = old_struct->repeat;
182 =item C<void destroy()>
190 VTABLE void destroy() {
191 Parrot_cx_delete_task(INTERP, SELF);
192 mem_sys_free(PMC_data(SELF));
197 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
199 Returns the timer info for C<key>.
205 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
206 Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
207 const FLOATVAL absolute_time = core_struct->birthtime + core_struct->duration;
210 case PARROT_TIMER_SEC:
211 return (INTVAL)absolute_time;
212 case PARROT_TIMER_USEC:
213 return (INTVAL)((absolute_time - (INTVAL)absolute_time) *1000000.0);
214 case PARROT_TIMER_REPEAT:
215 return (INTVAL) core_struct->repeat;
216 case PARROT_TIMER_INTERVAL:
217 return (INTVAL) core_struct->interval;
218 case PARROT_TIMER_RUNNING:
227 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
229 Returns the PMC associated with C<key>.
235 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
236 if (key == PARROT_TIMER_HANDLER) {
237 const Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
238 return core_struct->codeblock;
246 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
248 Returns the number associated with C<key>.
254 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
255 const Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
258 case PARROT_TIMER_NSEC:
259 return core_struct->birthtime + core_struct->duration;
260 case PARROT_TIMER_INTERVAL:
261 return core_struct->interval;
271 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
273 Sets the value associated with C<key> to C<value>.
279 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
280 Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
283 case PARROT_TIMER_SEC:
284 core_struct->duration = value;
286 case PARROT_TIMER_USEC:
287 core_struct->duration += value / 1000000.0;
289 case PARROT_TIMER_REPEAT:
290 core_struct->repeat = value;
292 case PARROT_TIMER_INTERVAL:
293 core_struct->interval = value;
295 case PARROT_TIMER_RUNNING:
297 Parrot_cx_schedule_task(INTERP, SELF);
299 Parrot_cx_delete_task(INTERP, SELF);
302 real_exception(INTERP, NULL, INVALID_OPERATION,
303 "Unknown timer type in Timer.set_integer_keyed_int: %d",
310 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
312 Sets the PMC associated with C<key> to C<*value>.
318 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
319 if (key == PARROT_TIMER_HANDLER) {
320 Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
321 core_struct->codeblock = value;
327 =item C<opcode_t *invoke(void *next)>
329 Adds the timer to the event queue.
335 VTABLE opcode_t *invoke(void *next) {
336 Parrot_cx_schedule_task(INTERP, SELF);
337 return (opcode_t *)next;
342 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
344 Sets the floating-point value associated with C<key> to C<value>.
350 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
351 Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
354 case PARROT_TIMER_NSEC:
355 core_struct->duration = value;
357 case PARROT_TIMER_INTERVAL:
358 core_struct->interval = value;
361 real_exception(INTERP, NULL, INVALID_OPERATION,
362 "Unknown timer attribute in Timer.set_number_keyed_int: %d", key);
377 * c-file-style: "parrot"
379 * vim: expandtab shiftwidth=4: