Skip to content
This repository
branch: eval_pmc
Fetching contributors…

Cannot retrieve contributors at this time

file 181 lines (127 sloc) 4.222 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
/*
Copyright (C) 2001-2011, Parrot Foundation.

=head1 NAME

src/pmc/managedstruct.pmc - Memory-managed C struct

=head1 DESCRIPTION

C<ManagedStruct> extends C<UnManagedStruct> to provide a class to hold C
C<struct> values that Parrot is responsible for disposing of.

=head2 Methods

=over 4

=cut

*/

typedef void (*custom_free_func_t)(PARROT_INTERP, void *ptr, void *priv);
typedef PMC * (*custom_clone_func_t)(PARROT_INTERP, PMC *ptr, void *priv);

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

pmclass ManagedStruct extends UnManagedStruct auto_attrs {
    /* if custom_free_func and ptr (inherited from UnManagedStruct) are both set,
     * custom_free_func is called before the normal destroy() function does any
     * work.
     */
    ATTR void (*custom_free_func)(PARROT_INTERP, void *, void *);
    ATTR void *custom_free_priv;
    /* if custom_clone_func is set, it will be called *instead* of the normal
     * clone() function logic.
     */
    ATTR PMC * (*custom_clone_func)(PARROT_INTERP, PMC *ptr, void *priv);
    ATTR void *custom_clone_priv;

/*

=item C<void init()>

Initializes an empty struct.

=cut

*/

    VTABLE void init() {
        UNUSED(INTERP)
        PObj_custom_destroy_SET(SELF);
    }

/*

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

Initializes the struct with C<*value>.

=cut

*/

    VTABLE void init_pmc(PMC *value) {
        SELF.init();
        SELF.set_pmc(value);
    }

/*

=item C<void destroy()>

Destroys the struct, freeing the allocated memory.

If the "custom_free_func" attribute is set, it is called to free the pointer.
Otherwise, mem_gc_free() is used.

=cut

*/

    VTABLE void destroy() {
        void * const ptr = PARROT_MANAGEDSTRUCT(SELF)->ptr;
        if (ptr) {
            const custom_free_func_t free_func = PARROT_MANAGEDSTRUCT(SELF)->custom_free_func;
            if (free_func) {
                void * const free_data = PARROT_MANAGEDSTRUCT(SELF)->custom_free_priv;
                free_func(INTERP, ptr, free_data);
            }
            else {
                mem_gc_free(INTERP, ptr);
            }
        }
    }

/*

=item C<void set_integer_native(INTVAL value)>

(Re)allocates C<value> bytes for the struct.

=cut

*/

    VTABLE void set_integer_native(INTVAL value) {
        Parrot_ManagedStruct_attributes * const attrs = PARROT_MANAGEDSTRUCT(SELF);

        if (attrs->ptr && !value) {
            mem_gc_free(INTERP, attrs->ptr);
            attrs->ptr = NULL;
            attrs->size = 0;
        }
        else if (value && !attrs->ptr) {
            attrs->ptr = Parrot_gc_allocate_memory_chunk_with_interior_pointers(
                    INTERP, (size_t)value);
            attrs->size = value;
        }
        else if (value && attrs->ptr) {
            if (attrs->size != value) {
                attrs->ptr =
                    Parrot_gc_reallocate_memory_chunk_with_interior_pointers(INTERP,
                        attrs->ptr, (size_t)value, attrs->size);
                attrs->size = value;
            }
        }

        return;
    }


/*

=item C<PMC * clone()>

Creates a clone of this PMC; clones any unmanaged memory it holds too.

If the "custom_clone_func" attribute is set, it is called to clone the PMC.
Otherwise, a basic (shallow copy) clone is performed, as there's no general way
of knowing how to make a deep copy of the pointer contents.

=cut

*/

    VTABLE PMC *clone() {
        const custom_clone_func_t clone_func = PARROT_MANAGEDSTRUCT(SELF)->custom_clone_func;
        PMC *dest;
        if (clone_func) {
            void * const clone_data = PARROT_MANAGEDSTRUCT(SELF)->custom_clone_priv;
            return clone_func(INTERP, SELF, clone_data);
        }
        dest = Parrot_pmc_new_init(INTERP, SELF->vtable->base_type,
            PARROT_MANAGEDSTRUCT(SELF)->init);

        if (PARROT_MANAGEDSTRUCT(SELF)->ptr)
            memmove(PARROT_MANAGEDSTRUCT(dest)->ptr,
                    PARROT_MANAGEDSTRUCT(SELF)->ptr,
                    PARROT_MANAGEDSTRUCT(SELF)->size);

        return dest;
    }

}

/*

=back

=cut

*/

/*
 * Local variables:
 * c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
 */
Something went wrong with that request. Please try again.