Permalink
Browse files

[events] Add interface for event handling, add subtype attribute to t…

…ask.

git-svn-id: https://svn.parrot.org/parrot/trunk@23791 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 111ac11 commit d6808fe82f20123fb4ab3ede000f3115ceef92a2 @allisonrandal allisonrandal committed Dec 12, 2007
Showing with 229 additions and 7 deletions.
  1. +15 −0 include/parrot/scheduler.h
  2. +1 −0 include/parrot/scheduler_private.h
  3. +43 −1 src/pmc/eventhandler.pmc
  4. +60 −1 src/pmc/scheduler.pmc
  5. +24 −2 src/pmc/task.pmc
  6. +86 −3 src/scheduler.c
View
@@ -18,6 +18,21 @@
/* HEADERIZER BEGIN: src/scheduler.c */
PARROT_API
+void Parrot_cx_add_handler(PARROT_INTERP, NOTNULL(PMC *handler))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+PARROT_API
+PARROT_CAN_RETURN_NULL
+PMC * Parrot_cx_find_handler_for_task(PARROT_INTERP, NOTNULL(PMC *task))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+PARROT_API
+void Parrot_cx_init_scheduler(PARROT_INTERP)
+ __attribute__nonnull__(1);
+
+PARROT_API
void Parrot_cx_runloop_end(PARROT_INTERP)
__attribute__nonnull__(1);
@@ -41,6 +41,7 @@ typedef struct Parrot_Task {
int priority; /* The priority of the task. */
int birthtime; /* A time stamp marking the creation of the task. */
STRING *type; /* The type of the task. */
+ STRING *subtype; /* The subtype of the task. */
STRING *status; /* The status of the task. */
PMC *codeblock; /* An (optional) codeblock for the task. */
PMC *interp; /* An (optional) interpreter structure for the task. */
View
@@ -11,7 +11,7 @@ src/pmc/eventhandler.pmc - a handler for events
A PMC that captures the state of the interpreter to invoke when handling an
Event.
-=head2 Methods
+=head2 Vtable Functions
=over 4
@@ -231,6 +231,48 @@ Runs the contained code, if any; this is what handles the event.
return (opcode_t *)next;
}
+
+/*
+
+=back
+
+=head2 Methods
+
+=over 4
+
+=cut
+
+*/
+
+/*
+
+=item C<PCCMETHOD can_handle(PMC *event)>
+
+Report whether the event handler can handle a particular type of event.
+
+=cut
+
+*/
+
+ PCCMETHOD can_handle(PMC *event) {
+ Parrot_EventHandler *handler_struct = PMC_data_typed(SELF, Parrot_EventHandler *);
+ if (event->vtable->base_type == enum_class_Task) {
+ PMC *type = VTABLE_get_attr_str(interp, event, CONST_STRING(interp, "type"));
+ STRING *type_str = VTABLE_get_string(interp, type);
+
+ if (string_equal(interp, type_str, CONST_STRING(interp, "event")) == 0) {
+ PMC *subtype = VTABLE_get_attr_str(interp, event, CONST_STRING(interp, "subtype"));
+ STRING *subtype_str = VTABLE_get_string(interp, subtype);
+
+ if (string_equal(interp, subtype_str, handler_struct->type) == 0) {
+ PCCRETURN(INTVAL 1);
+ }
+ }
+ }
+
+ PCCRETURN(INTVAL 0);
+ }
+
}
/*
View
@@ -10,7 +10,7 @@ src/pmc/scheduler.pmc - The concurrency scheduler
Implements the core concurrency scheduler.
-=head2 Functions
+=head2 Vtable Functions
=over 4
@@ -166,6 +166,7 @@ Retrieve the number of pending tasks in the scheduler's task list.
return VTABLE_elements(INTERP, core_struct->task_index);
}
+
/*
=item C<void delete_keyed_int(INTVAL key)>
@@ -340,6 +341,64 @@ Called after the scheduler has been thawed.
/* TODO: Rebuild the task index. */
}
+/*
+
+=back
+
+=head2 Methods
+
+=over 4
+
+=cut
+
+*/
+
+/*
+
+=item C<PCCMETHOD add_handler(PMC *handler)>
+
+Add a handler to the scheduler.
+
+=cut
+
+*/
+
+ PCCMETHOD add_handler(PMC *handler) {
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+ VTABLE_push_pmc(INTERP, core_struct->handlers, handler);
+ }
+/*
+
+=item C<PCCMETHOD find_handler(PMC *task)>
+
+Search for a handler for the given task. If no handler is found, return
+PMCNULL.
+
+=cut
+
+*/
+
+ PCCMETHOD find_handler(PMC *task) {
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+ INTVAL elements = VTABLE_elements(INTERP, core_struct->handlers);
+ INTVAL counter;
+
+ for (counter = 0; counter < elements; ++counter) {
+ PMC *handler = VTABLE_get_pmc_keyed_int(interp,
+ core_struct->handlers, counter);
+ INTVAL valid_handler = 0;
+ if (!PMC_IS_NULL(handler)) {
+ (INTVAL valid_handler) = PCCINVOKE(interp, handler, "can_handle", PMC *task);
+ if (valid_handler) {
+ PCCRETURN(PMC *handler);
+ }
+ }
+ }
+
+ PCCRETURN(PMC *PMCNULL);
+
+ }
+
}
/*
View
@@ -44,6 +44,7 @@ Initialize a concurrency task object.
PMC_data(SELF) = core_struct;
core_struct->id = 0;
core_struct->type = CONST_STRING(interp, "");
+ core_struct->subtype = CONST_STRING(interp, "");
core_struct->priority = 0;
core_struct->status = CONST_STRING(interp, "created");
core_struct->birthtime = 0;
@@ -70,6 +71,11 @@ An C<Integer> representing the task's unique identifier.
A C<String> representing the type of the task.
+=item C<subtype>
+
+A C<String> representing the subtype of the task. (Used mostly by events and
+exceptions to identify appropriate handlers.)
+
=item C<priority>
An C<Integer> representing the task's priority, from 0 to 100.
@@ -169,6 +175,10 @@ Gets the value of an attribute for this task.
value = pmc_new(interp, enum_class_String);
VTABLE_set_string_native(interp, value, core_struct->type);
}
+ else if (string_equal(interp, name, CONST_STRING(interp, "subtype")) == 0) {
+ value = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, value, core_struct->subtype);
+ }
else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
value = pmc_new(interp, enum_class_Integer);
VTABLE_set_integer_native(interp, value, core_struct->priority);
@@ -203,6 +213,9 @@ Sets the value of an attribute for this task.
else if (string_equal(interp, name, CONST_STRING(interp, "type")) == 0) {
core_struct->type = VTABLE_get_string(interp, value);
}
+ else if (string_equal(interp, name, CONST_STRING(interp, "subtype")) == 0) {
+ core_struct->subtype = VTABLE_get_string(interp, value);
+ }
else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
core_struct->priority = VTABLE_get_integer(interp, value);
}
@@ -329,7 +342,10 @@ Used to archive the task.
/* 4) freeze task type */
VTABLE_push_string(INTERP, io, core_struct->type);
- /* 5) freeze task status */
+ /* 5) freeze task subtype */
+ VTABLE_push_string(INTERP, io, core_struct->subtype);
+
+ /* 6) freeze task status */
VTABLE_push_string(INTERP, io, core_struct->status);
}
@@ -358,7 +374,10 @@ Used to unarchive the task.
/* 4. thaw task type */
STRING * const type = VTABLE_shift_string(INTERP, io);
- /* 5. thaw task status */
+ /* 5. thaw task subtype */
+ STRING * const subtype = VTABLE_shift_string(INTERP, io);
+
+ /* 6. thaw task status */
STRING * const status = VTABLE_shift_string(INTERP, io);
/* Allocate the task's core data struct and set custom flags. */
@@ -373,6 +392,9 @@ Used to unarchive the task.
/* Set the task's type to the frozen type */
PARROT_TASK(SELF)->type = type;
+ /* Set the task's subtype to the frozen subtype */
+ PARROT_TASK(SELF)->subtype = subtype;
+
/* Set the task's priority to the frozen priority */
PARROT_TASK(SELF)->priority = priority;
View
@@ -23,6 +23,8 @@ exceptions, async I/O, and concurrent tasks (threads).
#include "parrot/parrot.h"
#include "parrot/scheduler_private.h"
+#include "scheduler.str"
+
#define CX_DEBUG 0
/* HEADERIZER HFILE: include/parrot/scheduler.h */
@@ -125,9 +127,13 @@ scheduler_runloop(NOTNULL(PMC *scheduler))
else {
/* Otherwise, the runloop sleeps until a task is pending */
#if CX_DEBUG
- fprintf(stderr, "sleeping in scheduler runloop\n");
+ fprintf(stderr, "sleeping in scheduler runloop\n");
#endif
Parrot_cx_runloop_sleep(scheduler);
+#if CX_DEBUG
+ fprintf(stderr, "waking in scheduler runloop\n");
+#endif
+/* LOCK(sched_struct->lock); */
}
} /* end runloop */
@@ -162,16 +168,27 @@ static int
Parrot_cx_handle_tasks(PARROT_INTERP, NOTNULL(PMC *scheduler))
{
while (VTABLE_get_integer(interp, scheduler) > 0) {
+ PMC *handler;
PMC *task = VTABLE_pop_pmc(interp, scheduler);
const INTVAL tid = VTABLE_get_integer(interp, task);
+#if CX_DEBUG
+ fprintf(stderr, "Found task ID # %d\n", (int) tid);
+#endif
/* When sent a terminate task, notify the scheduler */
if (TASK_terminate_runloop_TEST(task)) {
SCHEDULER_terminate_runloop_SET(scheduler);
}
+ else {
+ handler = Parrot_cx_find_handler_for_task(interp, task);
+ if (!PMC_IS_NULL(handler)) {
#if CX_DEBUG
- fprintf(stderr, "Found task ID # %d\n", (int) tid);
+ fprintf(stderr, "Found a handler.\n");
#endif
+/* VTABLE_invoke(interp, handler); */
+ }
+ }
+
VTABLE_delete_keyed_int(interp, scheduler, tid);
} /* end of pending tasks */
@@ -270,10 +287,76 @@ PARROT_API
void
Parrot_cx_schedule_task(PARROT_INTERP, NOTNULL(PMC *task))
{
- VTABLE_push_pmc(interp, interp->scheduler, task);
+ if (interp->scheduler)
+ VTABLE_push_pmc(interp, interp->scheduler, task);
+ else
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "Scheduler was not initialized for this interpreter.\n");
+}
+
+/*
+
+=item C<PARROT_API
+void
+Parrot_cx_add_handler(PARROT_INTERP, NOTNULL(PMC *handler))>
+
+Add a task handler to scheduler's list of handlers.
+
+=cut
+
+*/
+
+PARROT_API
+void
+Parrot_cx_add_handler(PARROT_INTERP, NOTNULL(PMC *handler))
+{
+ if (interp->scheduler)
+ Parrot_PCCINVOKE(interp, interp->scheduler,
+ CONST_STRING(interp, "add_handler"), "P->", handler);
+ else
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "Scheduler was not initialized for this interpreter.\n");
+ return;
}
/*
+
+=item C<PARROT_API
+PMC *
+Parrot_cx_find_handler_for_task(PARROT_INTERP, NOTNULL(PMC *task))>
+
+Retrieve a handler appropriate to a given task. If the scheduler has no
+appropriate handler, returns PMCNULL.
+
+=cut
+
+*/
+
+PARROT_API
+PARROT_CAN_RETURN_NULL
+PMC *
+Parrot_cx_find_handler_for_task(PARROT_INTERP, NOTNULL(PMC *task))
+{
+ PMC *handler = PMCNULL;
+#if CX_DEBUG
+ fprintf(stderr, "searching for handler\n");
+#endif
+
+ if (interp->scheduler)
+ Parrot_PCCINVOKE(interp, interp->scheduler,
+ CONST_STRING(interp, "find_handler"), "P->P", task, &handler);
+ else
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "Scheduler was not initialized for this interpreter.\n");
+
+#if CX_DEBUG
+ fprintf(stderr, "done searching for handler\n");
+#endif
+ return handler;
+}
+
+
+/*
* Local variables:
* c-file-style: "parrot"
* End:

0 comments on commit d6808fe

Please sign in to comment.