tagged release 0.6.4
[parrot.git] / src / pmc / task.pmc
blob277f28cce95aff68cd187fa1ce4fe9512e184d41
1 /*
2 Copyright (C) 2001-2007, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/task.pmc - A concurrent task
9 =head1 DESCRIPTION
11 Implements the basic task behavior for the concurrency scheduler.
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/scheduler_private.h"
24 pmclass Task need_ext {
25     ATTR INTVAL        id;        /* The task ID. */
26     ATTR INTVAL        priority;  /* The priority of the task. */
27     ATTR FLOATVAL      birthtime; /* The creation time stamp of the task. */
28     ATTR STRING       *type;      /* The type of the task. */
29     ATTR STRING       *subtype;   /* The subtype of the task. */
30     ATTR STRING       *status;    /* The status of the task. */
31     ATTR Parrot_Interp interp;    /* The interpreter that created the task. */
32     ATTR PMC          *codeblock; /* An (optional) codeblock for the task. */
33     ATTR PMC          *data;      /* Additional data for the task. */
34     ATTR char         *cb_data;   /* Additional data for a callback event. */
38 =item C<void init()>
40 Initialize a concurrency task object.
42 =cut
46     VTABLE void init() {
47         Parrot_Task * const core_struct = mem_allocate_zeroed_typed(Parrot_Task);
49         /* Set flags for custom DOD mark and destroy. */
50         PObj_custom_mark_SET(SELF);
51         PObj_active_destroy_SET(SELF);
53         /* Set up the core struct. */
54         PMC_data(SELF)           = core_struct;
55         core_struct->id          = 0;
56         core_struct->type        = CONST_STRING(interp, "");
57         core_struct->subtype     = CONST_STRING(interp, "");
58         core_struct->priority    = 0;
59         core_struct->status      = CONST_STRING(interp, "created");
60         core_struct->birthtime   = 0.0;
61         core_struct->codeblock   = PMCNULL;
62         core_struct->data        = PMCNULL;
63         core_struct->interp      = INTERP;
65         /* Make sure the flag is cleared by default */
66         TASK_terminate_runloop_CLEAR(SELF);
68     }
72 =item C<void init_pmc(PMC *data)>
74 Initializes a new Task with a C<Hash> PMC with any or all of the keys:
76 =over 4
78 =item C<id>
80 An C<Integer> representing the task's unique identifier.
82 =item C<type>
84 A C<String> representing the type of the task.
86 =item C<subtype>
88 A C<String> representing the subtype of the task. (Used mostly by events and
89 exceptions to identify appropriate handlers.)
91 =item C<priority>
93 An C<Integer> representing the task's priority, from 0 to 100.
95 =item C<status>
97 A C<String> representing the task's status, one of C<created>, C<invoked>,
98 C<inprocess>, or C<completed>.
100 =item C<birthtime>
102 The time at which this Task was inserted into the task list.
104 =item C<code>
106 A C<Sub> or descendent PMC related to this task.
108 =item C<interp>
110 An interpreter in which to execute this task.
112 =back
114 =cut
118     VTABLE void init_pmc(PMC *data) {
119         PMC         *elem;
120         Parrot_Task *core_struct;
122         if (! VTABLE_isa(INTERP, data, CONST_STRING(INTERP, "Hash")))
123             real_exception(INTERP, NULL, INVALID_OPERATION,
124                 "Task initializer must be a Hash");
126         core_struct = mem_allocate_zeroed_typed(Parrot_Task);
128         /* Set flags for custom DOD mark and destroy. */
129         PObj_custom_mark_SET(SELF);
130         PObj_active_destroy_SET(SELF);
132         /* Set up the core struct. */
133         PMC_data(SELF)           = core_struct;
135         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "id"));
136         if (! PMC_IS_NULL(elem))
137             core_struct->id = VTABLE_get_integer(INTERP, elem);
138         else
139             core_struct->id = 0;
141         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "type"));
142         if (! PMC_IS_NULL(elem))
143             core_struct->type = VTABLE_get_string(INTERP, elem);
144         else
145             core_struct->type = CONST_STRING(INTERP, "");
147         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "subtype"));
148         if (! PMC_IS_NULL(elem))
149             core_struct->subtype = VTABLE_get_string(INTERP, elem);
150         else
151             core_struct->subtype = CONST_STRING(INTERP, "");
153         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "priority"));
154         if (! PMC_IS_NULL(elem))
155             core_struct->priority = VTABLE_get_integer(INTERP, elem);
156         else
157             core_struct->priority = 0;
159         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "status"));
160         if (! PMC_IS_NULL(elem))
161             core_struct->status = VTABLE_get_string(INTERP, elem);
162         else
163             core_struct->status = CONST_STRING(INTERP, "created");
165         elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "birthtime"));
166         if (! PMC_IS_NULL(elem))
167             core_struct->birthtime = VTABLE_get_number(INTERP, elem);
168         else
169             core_struct->birthtime = 0.0;
171         core_struct->codeblock =
172             VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "code"));
173         core_struct->interp = (Parrot_Interp)
174             VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "data"));
175     }
179 =item C<PMC *clone()>
181 Create a copy of the task, resetting status, ID, and birthtime.
183 =cut
187     VTABLE PMC *clone() {
188         /* Create the new task PMC, of the same type of this one (we may
189          * have been subclassed). */
190         PMC * const copy  = pmc_new(interp, SELF->vtable->base_type);
191         Parrot_Task * const new_struct = PARROT_TASK(copy);
192         Parrot_Task * const old_struct = PARROT_TASK(SELF);
194         new_struct->codeblock = VTABLE_clone(interp, old_struct->codeblock);
195         new_struct->data      = old_struct->data;
196         new_struct->type      = old_struct->type;
197         new_struct->subtype   = old_struct->subtype;
198         new_struct->priority  = old_struct->priority;
200         return copy;
201     }
204 =item C<PMC *get_attr_str(STRING *name)>
206 Gets the value of an attribute for this task.
208 =cut
211     VTABLE PMC *get_attr_str(STRING *name) {
212         Parrot_Task * const core_struct = PARROT_TASK(SELF);
213         PMC *value;
215         if (string_equal(interp, name, CONST_STRING(interp, "id")) == 0) {
216             value = pmc_new(interp, enum_class_Integer);
217             VTABLE_set_integer_native(interp, value, core_struct->id);
218         }
219         else if (string_equal(interp, name, CONST_STRING(interp, "type")) == 0) {
220             value = pmc_new(interp, enum_class_String);
221             VTABLE_set_string_native(interp, value, core_struct->type);
222         }
223         else if (string_equal(interp, name, CONST_STRING(interp, "subtype")) == 0) {
224             value = pmc_new(interp, enum_class_String);
225             VTABLE_set_string_native(interp, value, core_struct->subtype);
226         }
227         else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
228             value = pmc_new(interp, enum_class_Integer);
229             VTABLE_set_integer_native(interp, value, core_struct->priority);
230         }
231         else if (string_equal(interp, name, CONST_STRING(interp, "status")) == 0) {
232             value = pmc_new(interp, enum_class_String);
233             VTABLE_set_string_native(interp, value, core_struct->status);
234         }
235         else if (string_equal(interp, name, CONST_STRING(interp, "birthtime")) == 0) {
236             value = pmc_new(interp, enum_class_Float);
237             VTABLE_set_number_native(interp, value, core_struct->birthtime);
238         }
239         else {
240             value = PMCNULL;
241         }
243         return value;
244     }
248 =item C<void set_attr_str(STRING *name, PMC *value)>
250 Sets the value of an attribute for this task.
252 =cut
255     VTABLE void set_attr_str(STRING *name, PMC *value) {
256         Parrot_Task * const core_struct = PARROT_TASK(SELF);
258         if (string_equal(interp, name, CONST_STRING(interp, "id")) == 0) {
259             core_struct->id = VTABLE_get_integer(interp, value);
260         }
261         else if (string_equal(interp, name, CONST_STRING(interp, "type")) == 0) {
262             core_struct->type = VTABLE_get_string(interp, value);
263         }
264         else if (string_equal(interp, name, CONST_STRING(interp, "subtype")) == 0) {
265             core_struct->subtype = VTABLE_get_string(interp, value);
266         }
267         else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
268             core_struct->priority = VTABLE_get_integer(interp, value);
269         }
270         else if (string_equal(interp, name, CONST_STRING(interp, "status")) == 0) {
271             core_struct->status = VTABLE_get_string(interp, value);
272         }
273         else if (string_equal(interp, name, CONST_STRING(interp, "birthtime")) == 0) {
274             core_struct->birthtime = VTABLE_get_number(interp, value);
275         }
276         else if (string_equal(interp, name, CONST_STRING(interp, "code")) == 0) {
277             core_struct->codeblock = value;
278         }
279         else if (string_equal(interp, name, CONST_STRING(interp, "data")) == 0) {
280             core_struct->data = value;
281         }
282     }
286 =item C<INTVAL get_integer()>
288 Retrieves the task ID for this task.
290 =cut
293     VTABLE INTVAL get_integer() {
294         const Parrot_Task * const core_struct = PARROT_TASK(SELF);
295         return core_struct->id;
296     }
300 =item C<void set_integer_native(INTVAL value)>
302 Sets the task ID of the task.
304 =cut
308     VTABLE void set_integer_native(INTVAL value) {
309         Parrot_Task * const core_struct = PARROT_TASK(SELF);
310         core_struct->id = value;
311     }
315 =item C<void set_number_native(FLOATVAL value)>
317 Sets the birthtime of the task.
319 =cut
323     VTABLE void set_number_native(FLOATVAL value) {
324         Parrot_Task * const core_struct = PARROT_TASK(SELF);
325         core_struct->birthtime = value;
326     }
330 =item C<void set_string_native(STRING *value)>
332 Sets the type of the task.
334 =cut
338     VTABLE void set_string_native(STRING *value) {
339         Parrot_Task * const core_struct = PARROT_TASK(SELF);
340         core_struct->type = value;
341     }
345 =item C<PMC *share_ro()>
347 Set this PMC as shared.
349 =cut
353     VTABLE PMC *share_ro() {
354         PMC *shared_self;
355         Parrot_Task *shared_struct;
357         if (PObj_is_PMC_shared_TEST(SELF))
358             return SELF;
360         shared_self = pt_shared_fixup(INTERP, SELF);
361         shared_struct = PARROT_TASK(shared_self);
363         if (!PMC_IS_NULL(shared_struct->codeblock))
364             shared_struct->codeblock = pt_shared_fixup(INTERP, shared_struct->codeblock);
366         if (!PMC_IS_NULL(shared_struct->data))
367             shared_struct->data = pt_shared_fixup(INTERP, shared_struct->data);
369         return shared_self;
370     }
374 =item C<void destroy()>
376 Free the task's underlying struct.
378 =cut
381     VTABLE void destroy() {
382         mem_sys_free(PMC_data(SELF));
383     }
387 =item C<void mark()>
389 Mark any referenced strings and PMCs.
391 =cut
394     VTABLE void mark() {
395         if (PARROT_TASK(SELF)) {
396             Parrot_Task * const core_struct = PARROT_TASK(SELF);
398             if (core_struct->codeblock)
399                 pobject_lives(interp, (PObj*)core_struct->codeblock);
400             if (core_struct->data)
401                 pobject_lives(interp, (PObj*)core_struct->data);
402         }
403     }
407 =item C<void visit(visit_info *info)>
409 This is used by freeze/thaw to visit the contents of the task.
411 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
413 =cut
417     VTABLE void visit(visit_info *info) {
418         Parrot_Task * const core_struct = PARROT_TASK(SELF);
419         PMC **pos;
421         /* 1) visit code block */
422         pos            = &core_struct->codeblock;
423         info->thaw_ptr = pos;
424         (info->visit_pmc_now)(INTERP, *pos, info);
425     }
429 =item C<void freeze(visit_info *info)>
431 Used to archive the task.
433 =cut
437     VTABLE void freeze(visit_info *info) {
438         IMAGE_IO * const io = info->image_io;
439         const Parrot_Task * const core_struct = PARROT_TASK(SELF);
441         /* 1) freeze task id */
442         VTABLE_push_integer(INTERP, io, core_struct->id);
444         /* 2) freeze task birthtime */
445         VTABLE_push_float(INTERP, io, core_struct->birthtime);
447         /* 3) freeze task priority */
448         VTABLE_push_integer(INTERP, io, core_struct->priority);
450         /* 4) freeze task type */
451         VTABLE_push_string(INTERP, io, core_struct->type);
453         /* 5) freeze task subtype */
454         VTABLE_push_string(INTERP, io, core_struct->subtype);
456         /* 6) freeze task status */
457         VTABLE_push_string(INTERP, io, core_struct->status);
458     }
462 =item C<void thaw(visit_info *info)>
464 Used to unarchive the task.
466 =cut
470     VTABLE void thaw(visit_info *info) {
471         IMAGE_IO * const io = info->image_io;
473         /* 1. thaw task id */
474         const INTVAL id = VTABLE_shift_integer(INTERP, io);
476         /* 2. thaw task birthtime */
477         const FLOATVAL birthtime = VTABLE_shift_float(INTERP, io);
479         /* 3. thaw task priority */
480         const INTVAL priority = VTABLE_shift_integer(INTERP, io);
482         /* 4. thaw task type */
483         STRING * const type = VTABLE_shift_string(INTERP, io);
485         /* 5. thaw task subtype */
486         STRING * const subtype = VTABLE_shift_string(INTERP, io);
488         /* 6. thaw task status */
489         STRING * const status = VTABLE_shift_string(INTERP, io);
491         /* Allocate the task's core data struct and set custom flags. */
492         SELF.init();
494         /* Set the task's id to the frozen id */
495         PARROT_TASK(SELF)->id = id;
497         /* Set the task's birthtime to the frozen birthtime */
498         PARROT_TASK(SELF)->birthtime = birthtime;
500         /* Set the task's type to the frozen type */
501         PARROT_TASK(SELF)->type = type;
503         /* Set the task's subtype to the frozen subtype */
504         PARROT_TASK(SELF)->subtype = subtype;
506         /* Set the task's priority to the frozen priority */
507         PARROT_TASK(SELF)->priority = priority;
509         /* Set the task's status to the frozen status */
510         PARROT_TASK(SELF)->status = status;
512     }
516 =item C<void thawfinish(visit_info *info)>
518 Called after the task has been thawed.
520 =cut
524     void thawfinish(visit_info *info) {
525         Parrot_Task * core_struct = PARROT_TASK(SELF);
527         UNUSED(core_struct); /* TODO: Rebuild the task index. */
528     }
534 =back
536 =head1 SEE ALSO
538 F<docs/pdds/pdd15_objects.pod>.
540 =cut
545  * Local variables:
546  *   c-file-style: "parrot"
547  * End:
548  * vim: expandtab shiftwidth=4:
549  */