2 Copyright (C) 2001-2008, Parrot 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/scheduler_private.h"
60 /* HEADERIZER HFILE: none */
61 /* HEADERIZER BEGIN: static */
62 /* HEADERIZER END: static */
64 pmclass Timer extends Task provides event provides invokable auto_attrs {
65 ATTR FLOATVAL duration; /* The duration of the timer pause */
66 ATTR FLOATVAL interval; /* How often to repeat */
67 ATTR INTVAL repeat; /* Whether to repeat:
68 * 0 = run once (no repeat), -1 = forever */
74 Initializes the timer.
81 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
83 /* Set flags for custom GC mark and destroy. */
84 PObj_custom_mark_SET(SELF);
85 PObj_custom_destroy_SET(SELF);
87 /* Set up the core struct. */
89 core_struct->type = CONST_STRING(INTERP, "timer");
90 core_struct->subtype = CONST_STRING(INTERP, "");
91 core_struct->priority = 0;
92 core_struct->status = CONST_STRING(interp, "created");
93 core_struct->birthtime = 0.0;
94 core_struct->codeblock = PMCNULL;
95 core_struct->interp = INTERP;
96 core_struct->duration = 0.0;
97 core_struct->interval = 0.0;
98 core_struct->repeat = 0;
100 /* Make sure the flag is cleared by default */
101 TASK_terminate_runloop_CLEAR(SELF);
106 =item C<void init_pmc(PMC *init)>
108 Takes an even-length collection of keys and values.
114 VTABLE void init_pmc(PMC *init) {
115 const INTVAL n = VTABLE_get_integer(INTERP, init);
120 for (i = 0; i < n; i += 2) {
121 const INTVAL key = VTABLE_get_integer_keyed_int(INTERP, init, i);
123 case PARROT_TIMER_SEC:
124 case PARROT_TIMER_USEC:
125 case PARROT_TIMER_REPEAT:
126 case PARROT_TIMER_RUNNING:
128 const INTVAL val = VTABLE_get_integer_keyed_int(INTERP, init, i+1);
129 SELF.set_integer_keyed_int(key, val);
132 case PARROT_TIMER_NSEC:
134 const FLOATVAL nval = VTABLE_get_number_keyed_int(INTERP, init, i+1);
135 SELF.set_number_keyed_int(key, nval);
138 case PARROT_TIMER_HANDLER:
140 PMC * const pval = VTABLE_get_pmc_keyed_int(INTERP, init, i+1);
141 SELF.set_pmc_keyed_int(key, pval);
152 =item C<PMC *clone()>
154 Create a copy of the timer, resetting status, id, and birthtime.
160 VTABLE PMC *clone() {
161 PMC * const copy = SUPER();
162 Parrot_Timer_attributes * const new_struct = PARROT_TIMER(copy);
163 Parrot_Timer_attributes * const old_struct = PARROT_TIMER(SELF);
165 new_struct->duration = old_struct->duration;
166 new_struct->interval = old_struct->interval;
167 new_struct->repeat = old_struct->repeat;
174 =item C<void destroy()>
182 VTABLE void destroy() {
183 Parrot_cx_delete_task(INTERP, SELF);
188 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
190 Returns the timer info for C<key>.
196 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
197 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
198 const FLOATVAL absolute_time = core_struct->birthtime + core_struct->duration;
201 case PARROT_TIMER_SEC:
202 return (INTVAL)absolute_time;
203 case PARROT_TIMER_USEC:
204 return (INTVAL)((absolute_time - (INTVAL)absolute_time) *1000000.0);
205 case PARROT_TIMER_REPEAT:
206 return (INTVAL) core_struct->repeat;
207 case PARROT_TIMER_INTERVAL:
208 return (INTVAL) core_struct->interval;
209 case PARROT_TIMER_RUNNING:
218 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
220 Returns the PMC associated with C<key>.
226 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
227 if (key == PARROT_TIMER_HANDLER) {
228 const Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
229 return core_struct->codeblock;
237 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
239 Returns the number associated with C<key>.
245 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
246 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
249 case PARROT_TIMER_NSEC:
250 return core_struct->birthtime + core_struct->duration;
251 case PARROT_TIMER_INTERVAL:
252 return core_struct->interval;
262 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
264 Sets the value associated with C<key> to C<value>.
270 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
271 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
274 case PARROT_TIMER_SEC:
275 core_struct->duration = value;
277 case PARROT_TIMER_USEC:
278 core_struct->duration += value / 1000000.0;
280 case PARROT_TIMER_REPEAT:
281 core_struct->repeat = value;
283 case PARROT_TIMER_INTERVAL:
284 core_struct->interval = value;
286 case PARROT_TIMER_RUNNING:
288 Parrot_cx_schedule_task(INTERP, SELF);
290 Parrot_cx_delete_task(INTERP, SELF);
293 Parrot_ex_throw_from_c_args(INTERP, NULL,
294 EXCEPTION_INVALID_OPERATION,
295 "Unknown timer type in Timer.set_integer_keyed_int: %d",
302 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
304 Sets the PMC associated with C<key> to C<*value>.
310 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
311 if (key == PARROT_TIMER_HANDLER) {
313 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
314 core_struct->codeblock = value;
316 SET_ATTR_codeblock(INTERP, SELF, value);
322 =item C<opcode_t *invoke(void *next)>
324 Adds the timer to the event queue.
330 VTABLE opcode_t *invoke(void *next) {
331 Parrot_cx_schedule_task(INTERP, SELF);
332 return (opcode_t *)next;
337 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
339 Sets the floating-point value associated with C<key> to C<value>.
345 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
346 Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
349 case PARROT_TIMER_NSEC:
350 core_struct->duration = value;
352 case PARROT_TIMER_INTERVAL:
353 core_struct->interval = value;
356 Parrot_ex_throw_from_c_args(INTERP, NULL,
357 EXCEPTION_INVALID_OPERATION,
358 "Unknown timer attribute in Timer.set_number_keyed_int: %d",
374 * c-file-style: "parrot"
376 * vim: expandtab shiftwidth=4: