Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: sixparrot
Fetching contributors…

Cannot retrieve contributors at this time

379 lines (235 sloc) 8.458 kb
/*
Copyright (C) 2001-2012, Parrot Foundation.
=head1 NAME
src/pmc/scheduler.pmc - The concurrency scheduler
=head1 DESCRIPTION
Implements the core concurrency scheduler.
=head2 Vtable Functions
=over 4
=cut
*/
#include "parrot/scheduler_private.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass Scheduler auto_attrs {
ATTR INTVAL id; /* The scheduler's ID. */
ATTR PMC *handlers; /* The list of currently active handlers. */
ATTR PMC *messages; /* A message queue used for communication
between schedulers. */
ATTR PMC *task_queue; /* List of tasks/green threads waiting to run */
ATTR PMC *foreign_tasks; /* List of tasks/green threads waiting to run */
ATTR Parrot_mutex task_queue_lock;
ATTR PMC *alarms; /* List of future alarms ordered by time */
ATTR PMC *all_tasks; /* Hash of all active tasks by ID */
ATTR UINTVAL next_task_id; /* ID to assign to the next created task */
ATTR Parrot_Interp interp; /* A link to the scheduler's interpreter. */
/*
=item C<void init()>
Initializes a concurrency scheduler object.
=cut
*/
VTABLE void init() {
Parrot_Scheduler_attributes * const core_struct =
(Parrot_Scheduler_attributes *) PMC_data(SELF);
/* Set flags for custom GC mark and destroy. */
PObj_custom_mark_SET(SELF);
PObj_custom_destroy_SET(SELF);
/* Set up the core struct. */
core_struct->id = 0;
core_struct->next_task_id = 0;
core_struct->interp = INTERP;
/* TODO: Do we need to eagerly create all these PMCs, or can we create
them lazily on demand? */
core_struct->handlers = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
core_struct->messages = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
core_struct->task_queue = Parrot_pmc_new(INTERP, enum_class_PMCList);
core_struct->foreign_tasks = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
core_struct->alarms = Parrot_pmc_new(INTERP, enum_class_PMCList);
core_struct->all_tasks = Parrot_pmc_new(INTERP, enum_class_Hash);
MUTEX_INIT(core_struct->task_queue_lock);
/* Chandon TODO: Delete from int-keyed hash doesn't like me. */
/* VTABLE_set_integer_native(interp, core_struct->all_tasks, Hash_key_type_int); */
}
/*
=item C<void init_pmc(PMC *data)>
Initializes a new Scheduler with a C<Hash> PMC with any or all of the keys:
=over 4
=item C<id>
An C<Integer> representing the unique identifier for this scheduler.
=back
=cut
*/
VTABLE void init_pmc(PMC *data) {
PMC *elem;
Parrot_Scheduler_attributes *core_struct;
if (!VTABLE_isa(INTERP, data, CONST_STRING(INTERP, "Hash")))
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"Scheduler initializer must be a Hash");
SELF.init();
core_struct = PARROT_SCHEDULER(SELF);
elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "id"));
if (!PMC_IS_NULL(elem))
core_struct->id = VTABLE_get_integer(INTERP, elem);
}
/*
=item C<void push_pmc(PMC *value)>
Inserts a task into the task list.
=cut
*/
void push_pmc(PMC *task) {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
LOCK(core_struct->task_queue_lock);
VTABLE_push_pmc(INTERP, core_struct->task_queue, task);
UNLOCK(core_struct->task_queue_lock);
}
/*
=item C<void unshift_pmc(PMC *value)>
Inserts a task into the head of the task list.
=cut
*/
void unshift_pmc(PMC *task) {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
LOCK(core_struct->task_queue_lock);
VTABLE_unshift_pmc(INTERP, core_struct->task_queue, task);
UNLOCK(core_struct->task_queue_lock);
}
/*
=item C<PMC *shift_pmc()>
Retrieves the next task from the task list.
=cut
*/
VTABLE PMC *shift_pmc() {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
PMC * task;
LOCK(core_struct->task_queue_lock);
task = VTABLE_shift_pmc(INTERP, core_struct->task_queue);
UNLOCK(core_struct->task_queue_lock);
return task;
}
/*
=item C<INTVAL get_integer()>
Retrieves the number of pending tasks in the scheduler's task list.
=cut
*/
VTABLE INTVAL get_integer() {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
INTVAL elements;
LOCK(core_struct->task_queue_lock);
elements = VTABLE_elements(INTERP, PARROT_SCHEDULER(SELF)->task_queue);
UNLOCK(core_struct->task_queue_lock);
return elements;
}
/*
=item C<void destroy()>
Frees the scheduler's underlying struct.
=cut
*/
VTABLE void destroy() {
UNUSED(INTERP)
UNUSED(SELF)
}
/*
=item C<void mark()>
Marks any referenced strings and PMCs as live.
=cut
*/
VTABLE void mark() {
if (PARROT_SCHEDULER(SELF)) {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->handlers);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->messages);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->task_queue);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->foreign_tasks);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->alarms);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->all_tasks);
}
}
/*
=item C<void visit(PMC *info)>
Visits the contents of the scheduler (used by freeze/thaw).
C<*info> is the visit info (see F<include/parrot/pmc_freeze.h>).
=cut
*/
VTABLE void visit(PMC *info) {
/* 1) visit task list */
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, task_queue);
/* 2) visit the handlers */
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, handlers);
/* 3) visit the alarms */
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, alarms);
/* 3) visit all tasks */
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, all_tasks);
}
/*
=item C<void freeze(PMC *info)>
Archives the scheduler.
=cut
*/
VTABLE void freeze(PMC *info) {
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
/* 1) freeze scheduler id */
VTABLE_push_integer(INTERP, info, core_struct->id);
}
/*
=item C<void thaw(PMC *info)>
Unarchives the scheduler.
=cut
*/
VTABLE void thaw(PMC *info) {
/* 1. thaw scheduler id */
const INTVAL id = VTABLE_shift_integer(INTERP, info);
/* Allocate the scheduler's core data struct and set custom flags. */
SELF.init();
/* Set the scheduler's id to the frozen id */
PARROT_SCHEDULER(SELF)->id = id;
}
/*
=item C<void thawfinish(PMC *info)>
Finishes thawing the scheduler.
=cut
*/
VTABLE void thawfinish(PMC *info) {
UNUSED(INTERP)
UNUSED(SELF)
UNUSED(info)
/* Parrot_cx_refresh_task_list(INTERP, SELF); */
}
/*
=back
=head2 Methods
=over 4
=cut
*/
/*
=item C<METHOD active_tasks()>
Returns a ResizablePMCArray containing pointers to all active tasks.
=cut
*/
METHOD active_tasks() {
Parrot_Scheduler_attributes *sdata = PARROT_SCHEDULER(SELF);
PMC * const tasks = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
PMC * const iter = Parrot_pmc_new_init(INTERP, enum_class_HashIterator, sdata->all_tasks);
while (!VTABLE_get_bool(INTERP, iter)) {
PMC * const pair = VTABLE_shift_pmc(INTERP, iter);
PMC * task = PMCNULL;
STRING * const value = CONST_STRING(INTERP, "value");
Parrot_pcc_invoke_method_from_c_args(INTERP, pair,
value, "->P", &task);
VTABLE_push_pmc(INTERP, tasks, task);
}
RETURN(PMC* tasks);
}
}
/*
=back
=head1 SEE ALSO
F<docs/pdds/pdd25_concurrency.pod>.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.