/*
Copyright (C) 2005-2008, The Perl Foundation.
$Id: /mirror/trunk/languages/lua/src/pmc/luathread.pmc 34462 2008-12-27T17:23:27.572097Z fperrad  $

=head1 NAME

pmc/luathread.pmc - Lua Thread

=head1 DESCRIPTION

C<LuaThread> extends C<LuaAny> to provide a class with the behaviour
of the Lua C<Thread> type.
This implementation is based on C<Parrot::Coroutine>.

=head2 Overloaded Methods

=over 4

=cut

*/

#include "lua_private.h"

static PMC* curr_func(PARROT_INTERP) {
    Parrot_Context *ctx = CONTEXT(interp);
    PMC *sub = ctx->current_sub;
    return sub;
}

static PMC* getcurrenv(PARROT_INTERP) {
    PMC *env = NULL;
    PMC *sub = curr_func(interp);
    if (sub) {
        env = PMC_metadata(sub);
    }
    return env;
}


pmclass LuaThread
    extends LuaAny
    dynpmc
    need_ext
    group lua_group
    hll lua {

/*

=item C<void init()>

Raises an exception. Use C<init_pmc()>.

=cut

*/
    VTABLE void init() {
        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
            "LuaThread init without sub");
    }

/*

=item C<void init_pmc(PMC *sub)>

=cut

*/
    VTABLE void init_pmc(PMC *sub) {
        PMC *classobj = Parrot_oo_get_class_str(INTERP,
                          const_string(INTERP, "Parrot::Coroutine"));
        PMC *init_args;

        if (PMC_IS_NULL(classobj))
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
                           "Parrot::Coroutine not found");

        init_args = pmc_new(INTERP, enum_class_Hash);
        VTABLE_set_pmc_keyed_str(INTERP, init_args,
                                 const_string(INTERP, "initial_sub"), sub);
        PMC_pmc_val(SELF) = VTABLE_instantiate(INTERP, classobj, init_args);
        PMC_metadata(SELF) = getcurrenv(INTERP);
        PObj_custom_mark_SET(SELF);
    }

/*

=item C<void mark()>

Marks the Parrot::Coroutine as live.

=cut

*/
    VTABLE void mark() {
        if (PMC_pmc_val(SELF))
            pobject_lives(INTERP, (PObj *)PMC_pmc_val(SELF));
        if (PMC_metadata(SELF))
            pobject_lives(INTERP, (PObj *)PMC_metadata(SELF));
    }

/*

=item C<STRING* name()>

Return the string "thread".

=cut

*/
    VTABLE STRING* name() {
        return const_string(INTERP, "thread");
    }

/*

=item C<PMC* clone()>

=cut

*/
    VTABLE PMC* clone() {
        return SELF;
    }

/*

=item C<PMC* get_attr_str(STRING *key)>

=cut

*/
    VTABLE PMC* get_attr_str(STRING *key) {
        return PMC_pmc_val(SELF);
    }

/*

=item C<STRING* get_string()>

=cut

*/
    VTABLE STRING* get_string() {
        return Parrot_sprintf_c(INTERP, "thread: %08X", SELF);
    }

/*

=item C<void set_pmc(PMC *value)>

=cut

*/
    VTABLE void set_pmc(PMC *value) {
        PMC_pmc_val(SELF) = PMC_pmc_val(value);
    }

/*

=back

=head2 non-Vtable Methods

=over 4

=item C<INTVAL is_equal(PMC *value)>

=cut

*/
    MULTI INTVAL is_equal(LuaThread value) {
        if (SELF == value)
            return (INTVAL)1;
        else
            return (INTVAL)0;
    }

    MULTI INTVAL is_equal(DEFAULT value) {
            return (INTVAL)0;
    }

/*

=back

=head2 Specific Methods

=over 4

=item C<PMC *getfenv()>

=cut

*/
    METHOD PMC* getfenv() {
        PMC *retval = PMC_metadata(SELF);

        if (!retval)
            retval = pmc_new(INTERP, dynpmc_LuaNil);

        RETURN(PMC *retval);
    }

/*

=item C<PMC* rawequal(PMC *value)>

=cut

*/
    METHOD PMC* rawequal(PMC *value) {
        PMC *retval = pmc_new(INTERP, dynpmc_LuaBoolean);

        if (PMC_type(SELF) == PMC_type(value) && SELF == value)
            VTABLE_set_integer_native(INTERP, retval, 1);
        else
            VTABLE_set_integer_native(INTERP, retval, 0);

        RETURN(PMC *retval);
    }

/*

=item C<void setfenv(PMC *env)>

=cut

*/
    METHOD void setfenv(PMC *env) {
        PMC_metadata(SELF) = env;
    }

}

/*

=back

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
