fix codetest failure - trailing whitespace
[parrot.git] / src / pmc / timer.pmc
blobde786c0ca04a8719d29547d6a2845cd3218f6598
1 /*
2 Copyright (C) 2001-2008, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/timer.pmc - Timer
9 =head1 SYNOPSIS
11     new P0, '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]
24     ...
25     set P0[.PARROT_TIMER_RUNNING], 0               # turn timer off
28 =head1 DESCRIPTION
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
35 code.
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
48 initializer.
50 =head2 Functions
52 =over 4
54 =cut
58 #include "parrot/scheduler_private.h"
60 pmclass Timer extends Task provides event auto_attrs {
61     ATTR FLOATVAL duration;  /* The duration of the timer pause */
62     ATTR FLOATVAL interval;  /* How often to repeat */
63     ATTR INTVAL   repeat;    /* Whether to repeat:
64                               * 0 = run once (no repeat), -1 = forever */
68 =item C<void init()>
70 Initializes the timer.
72 =cut
76     VTABLE void init() {
77         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
79         /* Set flags for custom GC mark and destroy. */
80         PObj_custom_mark_SET(SELF);
81         PObj_custom_destroy_SET(SELF);
83         /* Set up the core struct. */
84         core_struct->id          = 0;
85         core_struct->type        = CONST_STRING(interp, "timer");
86         core_struct->subtype     = CONST_STRING(interp, "");
87         core_struct->priority    = 0;
88         core_struct->status      = CONST_STRING(interp, "created");
89         core_struct->birthtime   = 0.0;
90         core_struct->codeblock   = PMCNULL;
91         core_struct->interp      = INTERP;
92         core_struct->duration    = 0.0;
93         core_struct->interval    = 0.0;
94         core_struct->repeat      = 0;
96         /* Make sure the flag is cleared by default */
97         TASK_terminate_runloop_CLEAR(SELF);
98     }
102 =item C<void init_pmc(PMC *init)>
104 See F<docs/pdds/pdd02_vtables.pod> for initializers.
106 =cut
110     VTABLE void init_pmc(PMC *init) {
111         const INTVAL n = VTABLE_get_integer(INTERP, init);
112         INTVAL       i;
114         SELF.init();
116         for (i = 0; i < n; i += 2) {
117             const INTVAL key = VTABLE_get_integer_keyed_int(INTERP, init, i);
118             switch (key) {
119               case PARROT_TIMER_SEC:
120               case PARROT_TIMER_USEC:
121               case PARROT_TIMER_REPEAT:
122               case PARROT_TIMER_RUNNING:
123                 {
124                     const INTVAL val = VTABLE_get_integer_keyed_int(INTERP, init, i+1);
125                     SELF.set_integer_keyed_int(key, val);
126                 }
127                 break;
128               case PARROT_TIMER_NSEC:
129                 {
130                     const FLOATVAL nval = VTABLE_get_number_keyed_int(INTERP, init, i+1);
131                     SELF.set_number_keyed_int(key, nval);
132                 }
133                 break;
134               case PARROT_TIMER_HANDLER:
135                 {
136                     PMC * const pval = VTABLE_get_pmc_keyed_int(INTERP, init, i+1);
137                     SELF.set_pmc_keyed_int(key, pval);
138                 }
139                 break;
140               default:
141                 break;
142             }
143         }
144     }
148 =item C<PMC *clone()>
150 Create a copy of the timer, resetting status, id, and birthtime.
152 =cut
156     VTABLE PMC *clone() {
157         PMC * const copy = SUPER();
158         Parrot_Timer_attributes * const new_struct = PARROT_TIMER(copy);
159         Parrot_Timer_attributes * const old_struct = PARROT_TIMER(SELF);
161         new_struct->duration  = old_struct->duration;
162         new_struct->interval  = old_struct->interval;
163         new_struct->repeat    = old_struct->repeat;
165         return copy;
166     }
170 =item C<void destroy()>
172 Destroys the timer.
174 =cut
178     VTABLE void destroy() {
179         Parrot_cx_delete_task(INTERP, SELF);
180     }
184 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
186 Returns the timer info for C<key>.
188 =cut
192     VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
193         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
194         const FLOATVAL absolute_time = core_struct->birthtime + core_struct->duration;
196         switch (key) {
197           case PARROT_TIMER_SEC:
198             return (INTVAL)absolute_time;
199           case PARROT_TIMER_USEC:
200             return (INTVAL)((absolute_time - (INTVAL)absolute_time) *1000000.0);
201           case PARROT_TIMER_REPEAT:
202             return (INTVAL) core_struct->repeat;
203           case PARROT_TIMER_INTERVAL:
204             return (INTVAL) core_struct->interval;
205           case PARROT_TIMER_RUNNING:
206             return 0;
207           default:
208             return -1;
209         }
210     }
214 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
216 Returns the PMC associated with C<key>.
218 =cut
222     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
223         if (key == PARROT_TIMER_HANDLER) {
224             const Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
225             return core_struct->codeblock;
226         }
228         return PMCNULL;
229     }
233 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
235 Returns the number associated with C<key>.
237 =cut
241     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
242         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
244         switch (key) {
245           case PARROT_TIMER_NSEC:
246             return core_struct->birthtime + core_struct->duration;
247           case PARROT_TIMER_INTERVAL:
248             return core_struct->interval;
249           default:
250             break;
251         }
253         return -1.0;
254     }
258 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
260 Sets the value associated with C<key> to C<value>.
262 =cut
266     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
267         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
269         switch (key) {
270           case PARROT_TIMER_SEC:
271             core_struct->duration = value;
272             break;
273           case PARROT_TIMER_USEC:
274             core_struct->duration += value / 1000000.0;
275             break;
276           case PARROT_TIMER_REPEAT:
277             core_struct->repeat = value;
278             break;
279           case PARROT_TIMER_INTERVAL:
280             core_struct->interval = value;
281             break;
282           case PARROT_TIMER_RUNNING:
283             if (value)
284                 Parrot_cx_schedule_task(INTERP, SELF);
285             else
286                 Parrot_cx_delete_task(INTERP, SELF);
287             break;
288           default:
289             Parrot_ex_throw_from_c_args(INTERP, NULL,
290                     EXCEPTION_INVALID_OPERATION,
291                     "Unknown timer type in Timer.set_integer_keyed_int: %d",
292                     key);
293         }
294     }
298 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
300 Sets the PMC associated with C<key> to C<*value>.
302 =cut
306     VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
307         if (key == PARROT_TIMER_HANDLER) {
309             Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
310             core_struct->codeblock = value;
312             SET_ATTR_codeblock(interp, SELF, value);
313         }
314     }
318 =item C<opcode_t *invoke(void *next)>
320 Adds the timer to the event queue.
322 =cut
326     VTABLE opcode_t *invoke(void *next) {
327         Parrot_cx_schedule_task(INTERP, SELF);
328         return (opcode_t *)next;
329     }
333 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
335 Sets the floating-point value associated with C<key> to C<value>.
337 =cut
341     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
342         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
344         switch (key) {
345           case PARROT_TIMER_NSEC:
346             core_struct->duration = value;
347             break;
348           case PARROT_TIMER_INTERVAL:
349             core_struct->interval = value;
350             break;
351           default:
352             Parrot_ex_throw_from_c_args(INTERP, NULL,
353                     EXCEPTION_INVALID_OPERATION,
354                     "Unknown timer attribute in Timer.set_number_keyed_int: %d",
355                     key);
356         }
357     }
362 =back
364 =cut
369  * Local variables:
370  *   c-file-style: "parrot"
371  * End:
372  * vim: expandtab shiftwidth=4:
373  */