/*
Copyright (C) 2001-2010, Parrot Foundation.
$Id: schedulermessage.pmc 46300 2010-05-05 03:58:50Z jimmy $

=head1 NAME

src/pmc/schedulermessage.pmc - The concurrency scheduler

=head1 DESCRIPTION

Implements a message passed between concurrency schedulers.

=head2 Vtable Functions

=over 4

=cut

*/

#include "parrot/scheduler_private.h"

/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */

pmclass SchedulerMessage auto_attrs {
    ATTR INTVAL  id;        /* The message's ID. */
    ATTR STRING *type;      /* The message's type. */
    ATTR PMC    *data;      /* Additional data for the message. */

/*

=item C<void init()>

Initialize a concurrency scheduler message object.

=cut

*/

    VTABLE void init() {
        Parrot_SchedulerMessage_attributes * const core_struct
            = (Parrot_SchedulerMessage_attributes *) PMC_data(SELF);

        /* Set flags for custom GC mark. */
        PObj_custom_mark_SET(SELF);

        /* Set up the core struct. */
        core_struct->id          = 0;
        core_struct->type        = CONST_STRING(INTERP, "");
        core_struct->data        = PMCNULL;
    }

/*

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

Initializes a new SchedulerMessage 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 message.

=item C<type>

A C<String> representing the unique type for this scheduler message.

=item C<data>

An C<PMC> representing the data passed in this scheduler message.

=back

=cut

*/

    VTABLE void init_pmc(PMC *data) {
        PMC                     *elem;
        Parrot_SchedulerMessage_attributes *core_struct;

        if (! VTABLE_isa(INTERP, data, CONST_STRING(INTERP, "Hash")))
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
                "message initializer must be a Hash");

        SELF.init();
        core_struct = PARROT_SCHEDULERMESSAGE(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);

        elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "type"));
        if (! PMC_IS_NULL(elem))
            core_struct->type = VTABLE_get_string(INTERP, elem);

        elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "data"));
        if (! PMC_IS_NULL(elem))
            core_struct->data = elem;
    }

/*

=item C<INTVAL get_integer()>

Retrieve the message ID.

=cut

*/

    VTABLE INTVAL get_integer() {
        const Parrot_SchedulerMessage_attributes * const
            core_struct = PARROT_SCHEDULERMESSAGE(SELF);
        UNUSED(INTERP);

        return core_struct->id;
    }

/*

=item C<void set_integer_native(INTVAL value)>

Set the message ID.

=cut

*/

    VTABLE void set_integer_native(INTVAL value) {
        Parrot_SchedulerMessage_attributes * const core_struct = PARROT_SCHEDULERMESSAGE(SELF);
        UNUSED(INTERP);
        core_struct->id = value;
    }


/*

=item C<STRING * get_string()>

Retrieve the message type.

=cut

*/

    STRING *  get_string() {
        const Parrot_SchedulerMessage_attributes * const core_struct =
            PARROT_SCHEDULERMESSAGE(SELF);
        UNUSED(INTERP);
        return core_struct->type;
    }

/*

=item C<void set_string_native(STRING *value)>

Set the message type.

=cut

*/

    VTABLE void set_string_native(STRING *value) {
        Parrot_SchedulerMessage_attributes * const core_struct = PARROT_SCHEDULERMESSAGE(SELF);
        UNUSED(INTERP);
        core_struct->type = value;
    }


/*

=item C<PMC *share_ro()>

Set this PMC as shared.

=cut

*/

    VTABLE PMC *share_ro() {
        PMC *shared_self;
        Parrot_SchedulerMessage_attributes *shared_struct;

        if (PObj_is_PMC_shared_TEST(SELF))
            return SELF;

        shared_self         = pt_shared_fixup(INTERP, SELF);
        shared_struct       = PARROT_SCHEDULERMESSAGE(shared_self);
        shared_struct->data = pt_shared_fixup(INTERP, shared_struct->data);

        return shared_self;
    }

/*

=item C<void mark()>

Mark any referenced strings and PMCs.

=cut

*/
    VTABLE void mark() {
        if (PARROT_SCHEDULERMESSAGE(SELF)) {
            Parrot_SchedulerMessage_attributes * const core_struct =
                PARROT_SCHEDULERMESSAGE(SELF);

            Parrot_gc_mark_STRING_alive(INTERP, core_struct->type);
            Parrot_gc_mark_PMC_alive(INTERP, core_struct->data);
        }
    }

/*

=item C<void visit(PMC *info)>

This is used by freeze/thaw to visit the contents of the scheduler message.

C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).

=cut

*/

    VTABLE void visit(PMC *info) {
        /* visit message data */
        VISIT_PMC(INTERP, info, PARROT_SCHEDULERMESSAGE(SELF)->data);
    }

/*

=item C<void freeze(PMC *info)>

Used to archive the scheduler message.

=cut

*/

    VTABLE void freeze(PMC *info) {
        Parrot_SchedulerMessage_attributes * const core_struct =
            PARROT_SCHEDULERMESSAGE(SELF);

        /* 1) freeze message id */
        VTABLE_push_integer(INTERP, info, core_struct->id);

        /* 2) freeze message type */
        VTABLE_push_string(INTERP, info, core_struct->type);
    }

/*

=item C<void thaw(PMC *info)>

Used to unarchive the scheduler message.

=cut

*/

    VTABLE void thaw(PMC *info) {
        /* 1. thaw message id */
        const INTVAL id = VTABLE_shift_integer(INTERP, info);

        /* 2. thaw message type */
        STRING * const type = VTABLE_shift_string(INTERP, info);

        /* Allocate the message's core data struct and set custom flags. */
        SELF.init();

        /* Set the message's id to the frozen id */
        PARROT_SCHEDULERMESSAGE(SELF)->id = id;

        /* Set the message's type to the frozen type */
        PARROT_SCHEDULERMESSAGE(SELF)->type = type;
    }

}

/*

=back

=head1 SEE ALSO

F<docs/pdds/pdd25_concurrency.pod>.

=cut

*/

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