tagged release 0.6.4
[parrot.git] / src / pmc / timer.pmc
blob04e9acb3dc74dccb8a1c5178e624589950430048
1 /*
2 Copyright (C) 2001-2008, The Perl 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/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 */
79 =item C<void init()>
81 Initializes the timer.
83 =cut
87     VTABLE void init() {
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;
96         core_struct->id          = 0;
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);
110     }
114 =item C<void init_pmc(PMC *init)>
116 See F<docs/pdds/pdd02_vtables.pod> for initializers.
118 =cut
122     VTABLE void init_pmc(PMC *init) {
123         const INTVAL n = VTABLE_get_integer(INTERP, init);
124         INTVAL       i;
126         SELF.init();
128         for (i = 0; i < n; i += 2) {
129             const INTVAL key = VTABLE_get_integer_keyed_int(INTERP, init, i);
130             switch (key) {
131                 case PARROT_TIMER_SEC:
132                 case PARROT_TIMER_USEC:
133                 case PARROT_TIMER_REPEAT:
134                 case PARROT_TIMER_RUNNING:
135                     {
136                     const INTVAL val = VTABLE_get_integer_keyed_int(INTERP, init, i+1);
137                     SELF.set_integer_keyed_int(key, val);
138                     }
139                     break;
140                 case PARROT_TIMER_NSEC:
141                     {
142                     const FLOATVAL nval = VTABLE_get_number_keyed_int(INTERP, init, i+1);
143                     SELF.set_number_keyed_int(key, nval);
144                     }
145                     break;
146                 case PARROT_TIMER_HANDLER:
147                     {
148                     PMC * const pval = VTABLE_get_pmc_keyed_int(INTERP, init, i+1);
149                     SELF.set_pmc_keyed_int(key, pval);
150                     }
151                     break;
152                 default:
153                     break;
154             }
155         }
156     }
160 =item C<PMC *clone()>
162 Create a copy of the timer, resetting status, id, and birthtime.
164 =cut
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;
177         return copy;
178     }
182 =item C<void destroy()>
184 Destroys the timer.
186 =cut
190     VTABLE void destroy() {
191         Parrot_cx_delete_task(INTERP, SELF);
192         mem_sys_free(PMC_data(SELF));
193     }
197 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
199 Returns the timer info for C<key>.
201 =cut
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;
209         switch (key) {
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:
219                 return 0;
220             default:
221                 return -1;
222         }
223     }
227 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
229 Returns the PMC associated with C<key>.
231 =cut
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;
239         }
241         return PMCNULL;
242     }
246 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
248 Returns the number associated with C<key>.
250 =cut
254     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
255         const Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
257         switch (key) {
258             case PARROT_TIMER_NSEC:
259                 return core_struct->birthtime + core_struct->duration;
260             case PARROT_TIMER_INTERVAL:
261                 return core_struct->interval;
262             default:
263                 break;
264         }
266         return -1.0;
267     }
271 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
273 Sets the value associated with C<key> to C<value>.
275 =cut
279     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
280         Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
282         switch (key) {
283             case PARROT_TIMER_SEC:
284                 core_struct->duration = value;
285                 break;
286             case PARROT_TIMER_USEC:
287                 core_struct->duration += value / 1000000.0;
288                 break;
289             case PARROT_TIMER_REPEAT:
290                 core_struct->repeat = value;
291                 break;
292             case PARROT_TIMER_INTERVAL:
293                 core_struct->interval = value;
294                 break;
295             case PARROT_TIMER_RUNNING:
296                 if (value)
297                     Parrot_cx_schedule_task(INTERP, SELF);
298                 else
299                     Parrot_cx_delete_task(INTERP, SELF);
300                 break;
301             default:
302                 real_exception(INTERP, NULL, INVALID_OPERATION,
303                     "Unknown timer type in Timer.set_integer_keyed_int: %d",
304                     key);
305         }
306     }
310 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
312 Sets the PMC associated with C<key> to C<*value>.
314 =cut
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;
322         }
323     }
327 =item C<opcode_t *invoke(void *next)>
329 Adds the timer to the event queue.
331 =cut
335     VTABLE opcode_t *invoke(void *next) {
336         Parrot_cx_schedule_task(INTERP, SELF);
337         return (opcode_t *)next;
338     }
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>.
346 =cut
350     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
351         Parrot_Timer * const core_struct = PARROT_TIMER(SELF);
353         switch (key) {
354             case PARROT_TIMER_NSEC:
355                 core_struct->duration = value;
356                 break;
357             case PARROT_TIMER_INTERVAL:
358                 core_struct->interval = value;
359                 break;
360             default:
361                 real_exception(INTERP, NULL, INVALID_OPERATION,
362                     "Unknown timer attribute in Timer.set_number_keyed_int: %d", key);
363         }
364     }
369 =back
371 =cut
376  * Local variables:
377  *   c-file-style: "parrot"
378  * End:
379  * vim: expandtab shiftwidth=4:
380  */