add generated_hello.pbc to examples-clean
[parrot.git] / src / pmc / timer.pmc
blobc52e7f563a89715c5f3fc274798785eb816959e7
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 /* 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 */
72 =item C<void init()>
74 Initializes the timer.
76 =cut
80     VTABLE void init() {
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. */
88         core_struct->id          = 0;
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);
102     }
106 =item C<void init_pmc(PMC *init)>
108 Takes an even-length collection of keys and values.
110 =cut
114     VTABLE void init_pmc(PMC *init) {
115         const INTVAL n = VTABLE_get_integer(INTERP, init);
116         INTVAL       i;
118         SELF.init();
120         for (i = 0; i < n; i += 2) {
121             const INTVAL key = VTABLE_get_integer_keyed_int(INTERP, init, i);
122             switch (key) {
123               case PARROT_TIMER_SEC:
124               case PARROT_TIMER_USEC:
125               case PARROT_TIMER_REPEAT:
126               case PARROT_TIMER_RUNNING:
127                 {
128                     const INTVAL val = VTABLE_get_integer_keyed_int(INTERP, init, i+1);
129                     SELF.set_integer_keyed_int(key, val);
130                 }
131                 break;
132               case PARROT_TIMER_NSEC:
133                 {
134                     const FLOATVAL nval = VTABLE_get_number_keyed_int(INTERP, init, i+1);
135                     SELF.set_number_keyed_int(key, nval);
136                 }
137                 break;
138               case PARROT_TIMER_HANDLER:
139                 {
140                     PMC * const pval = VTABLE_get_pmc_keyed_int(INTERP, init, i+1);
141                     SELF.set_pmc_keyed_int(key, pval);
142                 }
143                 break;
144               default:
145                 break;
146             }
147         }
148     }
152 =item C<PMC *clone()>
154 Create a copy of the timer, resetting status, id, and birthtime.
156 =cut
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;
169         return copy;
170     }
174 =item C<void destroy()>
176 Destroys the timer.
178 =cut
182     VTABLE void destroy() {
183         Parrot_cx_delete_task(INTERP, SELF);
184     }
188 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
190 Returns the timer info for C<key>.
192 =cut
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;
200         switch (key) {
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:
210             return 0;
211           default:
212             return -1;
213         }
214     }
218 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
220 Returns the PMC associated with C<key>.
222 =cut
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;
230         }
232         return PMCNULL;
233     }
237 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
239 Returns the number associated with C<key>.
241 =cut
245     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
246         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
248         switch (key) {
249           case PARROT_TIMER_NSEC:
250             return core_struct->birthtime + core_struct->duration;
251           case PARROT_TIMER_INTERVAL:
252             return core_struct->interval;
253           default:
254             break;
255         }
257         return -1.0;
258     }
262 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
264 Sets the value associated with C<key> to C<value>.
266 =cut
270     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
271         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
273         switch (key) {
274           case PARROT_TIMER_SEC:
275             core_struct->duration = value;
276             break;
277           case PARROT_TIMER_USEC:
278             core_struct->duration += value / 1000000.0;
279             break;
280           case PARROT_TIMER_REPEAT:
281             core_struct->repeat = value;
282             break;
283           case PARROT_TIMER_INTERVAL:
284             core_struct->interval = value;
285             break;
286           case PARROT_TIMER_RUNNING:
287             if (value)
288                 Parrot_cx_schedule_task(INTERP, SELF);
289             else
290                 Parrot_cx_delete_task(INTERP, SELF);
291             break;
292           default:
293             Parrot_ex_throw_from_c_args(INTERP, NULL,
294                     EXCEPTION_INVALID_OPERATION,
295                     "Unknown timer type in Timer.set_integer_keyed_int: %d",
296                     key);
297         }
298     }
302 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
304 Sets the PMC associated with C<key> to C<*value>.
306 =cut
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);
317         }
318     }
322 =item C<opcode_t *invoke(void *next)>
324 Adds the timer to the event queue.
326 =cut
330     VTABLE opcode_t *invoke(void *next) {
331         Parrot_cx_schedule_task(INTERP, SELF);
332         return (opcode_t *)next;
333     }
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>.
341 =cut
345     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
346         Parrot_Timer_attributes * const core_struct = PARROT_TIMER(SELF);
348         switch (key) {
349           case PARROT_TIMER_NSEC:
350             core_struct->duration = value;
351             break;
352           case PARROT_TIMER_INTERVAL:
353             core_struct->interval = value;
354             break;
355           default:
356             Parrot_ex_throw_from_c_args(INTERP, NULL,
357                     EXCEPTION_INVALID_OPERATION,
358                     "Unknown timer attribute in Timer.set_number_keyed_int: %d",
359                     key);
360         }
361     }
366 =back
368 =cut
373  * Local variables:
374  *   c-file-style: "parrot"
375  * End:
376  * vim: expandtab shiftwidth=4:
377  */