Browse files

fix count_eh opcode and add test for it, TT #212 rg++

git-svn-id: https://svn.parrot.org/parrot/trunk@36004 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 8571037 commit 9f26f4314e39ad0a728fd3a1f4edfb962630060a @NotFound NotFound committed Jan 25, 2009
Showing with 121 additions and 4 deletions.
  1. +10 −0 include/parrot/scheduler.h
  2. +1 −1 src/ops/core.ops
  3. +2 −1 src/pmc/scheduler.pmc
  4. +68 −1 src/scheduler.c
  5. +40 −1 t/pmc/exception.t
View
10 include/parrot/scheduler.h
@@ -36,6 +36,12 @@ void Parrot_cx_broadcast_message(PARROT_INTERP,
__attribute__nonnull__(2);
PARROT_EXPORT
+INTVAL Parrot_cx_count_handlers_local(PARROT_INTERP,
+ ARGIN(STRING *handler_type))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+PARROT_EXPORT
INTVAL Parrot_cx_count_handlers_typed(PARROT_INTERP,
ARGIN(STRING *handler_type))
__attribute__nonnull__(1)
@@ -171,6 +177,10 @@ void Parrot_cx_timer_invoke(PARROT_INTERP, ARGIN(PMC *timer))
#define ASSERT_ARGS_Parrot_cx_broadcast_message __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
|| PARROT_ASSERT_ARG(messagetype)
+#define ASSERT_ARGS_Parrot_cx_count_handlers_local \
+ __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+ PARROT_ASSERT_ARG(interp) \
+ || PARROT_ASSERT_ARG(handler_type)
#define ASSERT_ARGS_Parrot_cx_count_handlers_typed \
__attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
View
2 src/ops/core.ops
@@ -866,7 +866,7 @@ inline op rethrow(invar PMC) :flow {
}
inline op count_eh(out INT) {
- $1 = Parrot_cx_count_handlers_typed(interp,
+ $1 = Parrot_cx_count_handlers_local(interp,
string_from_cstring(interp, "exception", 9));
}
View
3 src/pmc/scheduler.pmc
@@ -513,11 +513,12 @@ If no type argument is passed, counts all handlers.
METHOD count_handlers(STRING *type :optional, INTVAL have_type :opt_flag) {
/* avoid uninitialized value warning */
PMC *handlers = NULL;
- INTVAL elements = VTABLE_elements(INTERP, handlers);
+ INTVAL elements;
INTVAL count = 0;
INTVAL index;
GET_ATTR_handlers(INTERP, SELF, handlers);
+ elements = VTABLE_elements(INTERP, handlers);
if (!have_type)
RETURN(INTVAL elements);
View
69 src/scheduler.c
@@ -559,6 +559,73 @@ Parrot_cx_delete_handler_local(PARROT_INTERP, ARGIN(STRING *handler_type))
/*
+=item C<INTVAL Parrot_cx_count_handlers_local>
+
+Count the number of active handlers of a particular type from the
+context's list of handlers.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+INTVAL
+Parrot_cx_count_handlers_local(PARROT_INTERP, ARGIN(STRING *handler_type))
+{
+ ASSERT_ARGS(Parrot_cx_count_handlers_local)
+ PMC *handlers = CONTEXT(interp)->handlers;
+ INTVAL elements;
+
+ if (PMC_IS_NULL(handlers))
+ return 0;
+
+ elements = VTABLE_elements(interp, handlers);
+
+ if (STRING_IS_NULL(handler_type) || STRING_IS_EMPTY(handler_type))
+ return elements;
+
+ /* Loop from newest handler to oldest handler. */
+ {
+ STRING *exception_str = CONST_STRING(interp, "exception");
+ STRING *event_str = CONST_STRING(interp, "event");
+ STRING *handler_str = CONST_STRING(interp, "ExceptionHandler");
+ INTVAL count = 0;
+ INTVAL index;
+ typedef enum { Hunknown, Hexception, Hevent } Htype;
+
+ const Htype htype =
+ (string_equal(interp, handler_type, exception_str) == 0) ?
+ Hexception :
+ (string_equal(interp, handler_type, event_str) == 0) ?
+ Hevent :
+ Hunknown;
+ STRING * const handler_name = (htype == Hexception) ?
+ handler_str : (STRING *) NULL;
+
+ for (index = 0; index < elements; ++index) {
+ PMC *handler = VTABLE_get_pmc_keyed_int(interp, handlers, index);
+ if (!PMC_IS_NULL(handler)) {
+ switch (htype) {
+ case Hexception:
+ if (VTABLE_isa(interp, handler, handler_name))
+ count++;
+ break;
+ case Hevent:
+ if (handler->vtable->base_type == enum_class_EventHandler)
+ count++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return count;
+ }
+}
+
+
+/*
+
=item C<void Parrot_cx_add_handler>
Add a task handler to scheduler's list of handlers.
@@ -625,7 +692,7 @@ Parrot_cx_count_handlers_typed(PARROT_INTERP, ARGIN(STRING *handler_type))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Scheduler was not initialized for this interpreter.\n");
- Parrot_PCCINVOKE(interp, interp->scheduler, CONST_STRING(interp, "count_handlers"), "S->I", handler_type, count);
+ Parrot_PCCINVOKE(interp, interp->scheduler, CONST_STRING(interp, "count_handlers"), "S->I", handler_type, &count);
return count;
}
View
41 t/pmc/exception.t
@@ -6,7 +6,7 @@ use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 30;
+use Parrot::Test tests => 31;
=head1 NAME
@@ -715,6 +715,45 @@ CODE
no segfault
OUTPUT
+pir_output_is( <<'CODE', <<'OUTPUT', "count_eh" );
+.sub main :main
+ $I0 = count_eh
+ if $I0 == 0 goto right_number1
+ print "not "
+ right_number1:
+ print "ok 1\n"
+ push_eh _handler1
+ push_eh _handler2
+ print "ok 2\n"
+ $I1 = count_eh
+ if $I1 == 2 goto right_number2
+ print "not "
+ right_number2:
+ print "ok 3\n"
+ pop_eh
+ pop_eh
+ print "ok 4\n"
+ $I2 = count_eh
+ if $I2 == 0 goto right_number3
+ print "not "
+ right_number3:
+ print "ok 5\n"
+ end
+_handler1:
+ print "first handler\n"
+ end
+_handler2:
+ print "second handler\n"
+ end
+.end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+OUTPUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4

0 comments on commit 9f26f43

Please sign in to comment.